MVC で「テーブル:モデル=1:1」が許されるのは小学生まで

本来、MVC の M はロジックを含み、C はイベントハンドリング、ウェブアプリケーションでいえば、画面遷移のみを担当します。

Catalystスキーマローダーをつかって、MyApp::Model::XXXX を自動生成してしまうと、「テーブル:モデル=1:1」という COBOL 全盛期みたいなアーキテクチャになってしまいます・・。それで、仕方なくロジックを C に書くようにすると、C が見るも無残なほど膨れ上がってしまい、メンテナンスの困難な製品ができあがります(笑)。RailsCatalyst でも、こういう作り方を推奨している雰囲気があります。

「テーブル:モデル=1:1」が許されるのは、RailsCatalyst で本当に小さいアプリケーションを作るときまでで、多少大きいアプリケーションを作ろうと思ったら、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>