モジュール分割の利点とスケルトンのリファクタリング

FuelPHP Advent Calendar 2012 4日目担当の@sa2yasuです。

昨日は@mikakane_infoさんの「FuelPHPのモジュール開発」でした。

今日はモジュール分割の話と
oilコマンドで作られるスケルトンコードに不満があったので、それを解消するFuelTaskを作った話になります。

モジュール化のメリット

 ここに書いてある通りなのですが、

モジュールとは、独立した MVC 要素のグループのことです。モジュールを使うと、コードを再利用しカプセル化することが可能になります。
モジュールは、通常、アプリケーションディレクトリの下の modules ディレクトリに置かれます。
結構な量のコードをもつ大きなプロジェクトを動かしている場合、 モジュールを使ってみてはいかがでしょうか。
モジュールは、物事をきちんと秩序立てて整理する助けになるでしょう。

例えばブログモジュールやアルバムモジュールのように、モジュールは独立して動作させることが可能です。
グローバルなコードに対するいかなるアクセスも行わず、モジュールのコントローラに対して直接ルーティングすることが出来ます。
モジュールは、純粋な HMVC コンテクストの中で使うことも出来ます。その場合、
ページ生成に必要な諸結果 (の一部) を得るために、コントローラは別のコントローラを呼び出すことが出来ます。

上記から考察するモジュール化のメリットは

  1. 独立したモジュールは再利用が可能
  2. 多人数での平行開発が容易(モジュール毎のチーム編成が可能)
  3. モジュール毎にディレクトリが分かれるので開発、保守性向上

と考えています。

実際のところ、つい先日までFuelPHPを用いて実案件でCMS構築をしていたのですが、コンテンツ部分はfuel/app/classesに、管理部分をモジュール化することでコードの見通しがよくなりました。
最初からfuel/app下に何もかも実装してしまうと後からモジュール分割する際にリファクタリングが大変だと思うので、開発初期の段階でサブシステムのイメージが決まっているなら、最初からモジュール化を検討する方がよいのかもしれません。

oilコマンドで生成されるスケルトンコードへの不満

これは僕のやり方なのかもしれませんが、FuelPHPで開発する時は、初めにモデル設計やURI設計をざっくりメモ書きして、
oilコマンドでひたすらコードスケルトンを生成、設計通りにルーティング、リレーションされるかどうかを確認してから細部の実装に取り掛かります。
ですが、現在のoilコマンドはmodulesディレクトリ以下にスケルトンコードを生成できるように出来ていないんですね(泣
ちなみにバージョン2.0ではmodule指定に対応するようです。
Make Scaffold support Modules [Feature]

ケルトンコードをmodules下にリファクタリングするTask

ということでoilコマンドで生成されるスケルトンコードへの不満を解消するFuelTaskを作ってみました。
やっていることは単純で、対象のパスのソースをmodules下にコピーしてnamespaceをつけたり、置換しているだけです。

インストール

https://github.com/ya-sasaki/fuel-module-refactor
git cloneでもzip展開でも良いのですが、使うのはmodule_refactor.phpのみですので、これをfuel/app/tasksに置いてください。

Scaffold生成

手っ取り早くScaffoldで例示しますね。

$ oil g scaffold sample_user user_id:varchar[10]
$ oil r migrate

http://localhost/sample/userにアクセスしてScaffoldが成功していることを確認

リファクタリングタスクの実行

以下のように実行できます。

$ oil r module_refactor <module_name> <type> <name> <delete>

第1引数はfuel/app/modules/です。
第2引数は"controller" or "model"です。指定した方をリファクタリングします。controllerを指定した場合は、あればですが、対象のapp/views, app/classes/viewもリファクタリングします。
第3引数はoil g したときのクラス名です。上記Scaffoldの例だと"sample_user"ですね。
第4引数はリファクタリング後にスケルトンコードを削除するかどうかを指定します。デフォルトはfalseです。

ScaffoldはMVC全部あるので以下のようにタスクを実行します。

$ oil r module_refactor test controller sample_user true
$ oil r module_refactor test model sample_user true

タスク実行後は、以前のURLはPage Not Found。http://localhost/test/sample/userリファクタリングしたScaffoldを確認できます。

がっつりコード書いた後のTask実行は試してないですけど多分失敗します(笑)
一応READMEでは「oil g・・・」直後のTask実行を推奨していますのであしからず。
(module_refactor.phpの$replacesで置換文字列を定義しているので、ココを上手く設定してあげれば綺麗にリファクタリングできるかも)

<?php
・・・・省略・・・
    private static $replaces = array(
        'controller' => array(
            'Controller_Template' => '\Controller_Template',
            'View::' => '\View::',
            'ViewModel' => '\ViewModel',
            'Viewmodel' => '\Viewmodel',
            'Response::' => '\Response::',
            'Input::' => '\Input::',
            'Session::' => '\Session::',
        ),
        'model' => array(
            'use Orm\Model;' => 'use \Orm\Model;',
            'Validation' => '\Validation',
        ),
        'view_model' => array(
            'Viewmodel' => '\Viewmodel',
            'ViewModel' => '\ViewModel',
        ),
        'views' => array(

        ),
    );