Perl Hackers Hub

第33回 MojoliciousでかんたんWebアプリケーション開発(3)

この記事を読むのに必要な時間:およそ 4 分

(1)こちら⁠2)こちらから。

Mojoliciousによる開発の勘所

ここからはMojoliciousを利用したWebアプリケーション開発におけるポイントを解説します。

解説する内容を反映したサンプルコードmojo_wikiを本誌サポートサイトに用意しましたので,参考にしてください。

MojoliciousとMojolicious::Lite

(2)までに作成したmyapp.plや掲示板アプリケーションは,Mojoliciousに含まれるマイクロWebフレームワークMojolicious::Liteを利用したアプリケーションです。ルーティング,コントローラ,ビューのテンプレートすべてを1つのファイルに定義できるので,CGIスクリプトのような感覚で気軽に開発できます。

ですが,アプリケーションが成長して規模が大きくなってきたり拡張性やメンテナンス性が必要になってくると,Mojolicious::Liteでは荷が重くなってきます。このような場合には通常のMojoliciousアプリケーションとして開発を行うことをお勧めします。

Mojoliciousアプリケーションは(2)と同様にmojogenerateで生成できますが,コマンドの引数はlite_appではなくappとなります。

$ mojo generate app

コマンドが完了すると,my_appディレクトリ配下に図5のディレクトリ構造が生成されます。各コンポーネントごとにファイルが分割されるので,Mojolicious::Liteのアプリケーションに比べて保守性,拡張性の高い開発ができます。

図5 Mojoliciousアプリケーションのディレクトリ構造

図5 Mojoliciousアプリケーションのディレクトリ構造

プロトタイピングでMojolicious::Liteアプリケーションを作成し,そのあとにMojoliciousアプリケーションへ移行して開発を継続することもできます。移行ガイドを参考にしてください。

モデルの実装

前述したとおり,Mojoliciousはモデルをサポートしていません。

前節の掲示板アプリケーションの場合は特にほかのインタフェース(コマンドラインツールやテストなど)での処理を必要としなかったため,コントローラにアプリケーションロジックを実装しました。ですが,多くのWebアプリケーションではコントローラ以外のインタフェースでもアプリケーションロジックが必要となることがあるため,アプリケーションロジックをモデルに格納し,コントローラから切り離して実装するのが効果的です。

リスト9は,O/RマッパのTengを利用したモデルの実装例です。

リスト9 モデルの実装例

package MyApp::Model;
use Mojo::Base -strict;

use Carp qw/carp croak/;
use Mojo::Loader qw/find_modules load_class/;
use Teng::Schema::Loader;

load_class $_ for find_modules __PACKAGE__;

my $INIT_ARGS;

sub init {
  my ($class, %args) = (shift, @_);
  if ($INIT_ARGS) {
    carp "already initialized";
  }
  else {
    $INIT_ARGS = \%args;
  }
  return $INIT_ARGS;
}

sub db {
  croak "You should init first" unless $INIT_ARGS;
  state $db = Teng::Schema::Loader->load(
    namespace => 'MyApp::DB',
    %$INIT_ARGS,
  );
}

1;

このモデルを各インタフェースで直接扱ってもよいのですが,SQLによるデータベース操作を抽象化するまでの実装となっているため,それぞれのインタフェースでアプリケーションロジックを少なからず実装しなければなりません。そこでこのモデルを内部的に利用する,次のようなモデルを作成します。

package MyApp::Model::User;
use Mojo::Base -strict;

sub table_name {'user'}

sub all {
  my $class = shift;
  MyApp::Model->db->search(
    table_name,
    {deleted => 0},
    {order_by => 'name'},
  );
}
...

このように実装することでコントローラからアプリケーションロジックを分離し,次のようにほかのイン タフェースでもモデルを利用できます。

MyApp::Model->init(connect_info => ...);
my $users = MyApp::Model::User->all();

著者プロフィール

hayajo(Hayato Imai)

新潟で働くエンジニア。

仕事ではPerlやGoによるアプリケーション開発やインフラ設計、構築、運用に携わる。

黒い画面が大好き。

コメント

コメントの記入