MVC で「テーブル:モデル=1:1」が許されるのは小学生まで
本来、MVC の M はロジックを含み、C はイベントハンドリング、ウェブアプリケーションでいえば、画面遷移のみを担当します。
Catalyst でスキーマローダーをつかって、MyApp::Model::XXXX を自動生成してしまうと、「テーブル:モデル=1:1」という COBOL 全盛期みたいなアーキテクチャになってしまいます・・。それで、仕方なくロジックを C に書くようにすると、C が見るも無残なほど膨れ上がってしまい、メンテナンスの困難な製品ができあがります(笑)。Rails や Catalyst でも、こういう作り方を推奨している雰囲気があります。
「テーブル:モデル=1:1」が許されるのは、Rails や Catalyst で本当に小さいアプリケーションを作るときまでで、多少大きいアプリケーションを作ろうと思ったら、MyApp::Model::XXXX を自動生成するなら、MyApp::Logic::XXXX がロジックを担当し、C からはこちらを呼ぶべきです。社内ではこのアーキテクチャパターンを勝手に「MLVCモデル」と読んでいます。C が膨れてきたなと思ったら、早いうちに「MLVCモデル」に移行することをオススメします。
コンポーネント | 説明 |
MyApp::Controller | 画面遷移を担当。MyApp::Logicを呼ぶ。 |
MyApp::Logic | ロジックを担当。場合によっては複数のMyApp::Modelを束ねる。インピーダンスミスマッチを吸収する。 |
MyApp::Model | O/Rマッパー。 |
MyApp::View | ビューを担当。MyAppから一度だけ呼ばれる。 |
Catalyst 用語でいう stash と session は MyApp::Logic 内で隠蔽化してしまうと幸せになれます。
追記
http://d.hatena.ne.jp/habuakihiro/20060617#1150545007
3.で生成される(予定の)UIをイメージしながら1.の作業をやるの? そりゃ大変だと思うよ。そりゃそんなスキルがあるなら、DB設計もさくさく出来るでしょうね。ERDレッスンなんてきっとみんな読む必要ないわ、うん。もしそんなスキルがなかったら? DB設計が単なるDTO設計に堕するわけですよ。画面にあわせたDB設計。みんなが馬鹿にしているCOBOLerが数10年やってきたことに戻っちゃうわけさ。あー、ご立派なことだこと。いっそISAMでも使ってりゃいいじゃん。
追記
$c->stash と $c->session を MyApp::Logic 内に隠蔽化すると、$c に依存してよくないという意見があります。しかしやりたいのは、M と V と C の分離であって、無理やり $c 依存をなくすことは本質的ではないと考えています。MyApp::View::TT が $c->stash を隠蔽化しているのと同じ感覚です。以下イメージコード。
package MyApp::Controller::Some; sub view : Local { my ( $self, $c ) = shift; $c->logic('FugaHogeMoge')->new($c)->view(); }
<!-- Some/view.tt --> <html><body> <h3>Fuga</h3> [% fuga.param1 %] [% fuga.param2 %] [% fuga.param3 %] <h3>Hoge</h3> [% hoge.param1 %] <h3>Moge</h3> [% moge.param1 %] [% moge.param2 %] </body></html>