web-dev-qa-db-ja.com

ファットモデル、スキニーコントローラー、MVCデザインパターン

銀行の例えでMVCを説明する ブログ投稿 を読んだばかりです。私はMVCフレームワーク(CakePHP)を使用したWebアプリケーション開発に数か月の経験があるので、基本は理解できますが、ロジックを配置する場所に欠陥のあるアプローチを取っていると思わせるテーマが見え始めました。

  • ファットモデル、スキニーコントローラー
  • モデルにできるだけ多くのビジネスロジックを保持する

私のアプリでは、モデルは拒食症であり、コントローラーは肥満です。コントローラにはすべてのビジネスロジックがあり、モデルには関連付けと検証ルール以外は何もありません。

コントローラをスキャンすると、モデルに含める必要のある多くのロジックを特定できるようになりました。

  • アプリにはアイテムを含むリストがあり、アイテムをランク付けできます。リストをランク付けした順序で並べ替えるロジックは、コントローラー内にあります。
  • 同様に、アイテム(アイテムモデル)にも画像(画像モデル)があります。各アイテムには、デフォルトの画像(itemsテーブルのimage_idで指定)が含まれる場合があります。アイテムがその画像とともに表示される場合、デフォルトの画像が最初に表示されます。私はコントローラーでこれを行うロジックを持っています。
  • リストが表示されると、関連するリストがサイドバーに表示されます。関連するリストを決定するロジックは、コントローラーにあります。

今私の質問に:

  1. 上で示した例では、これらは現在モデルに属するコントローラー内のロジックのインスタンスであると考えるのは正しい方向に進んでいますか?
  2. モデルに組み込まれるべき、Webアプリに共通のロジックの他の領域は何ですか?
  3. この問題を特定し、デザインパターンを変更することは、戦いの半分であると確信していますが、上記の例を取り上げてそのロジックをモデルに移行しようとしても、どこから始めればよいのかわかりません。ここにコードを投稿したり、優れた学習リソースにリンクしたりして、誰かが私を正しい方向に向けることができますか? CakePHP固有のヘルプは素晴らしいでしょうが、MVCなら何でも十分だと確信しています。
75

「正しい」答えを出すのは少し難しいです。なぜなら、それらのいくつかはフレームワークの詳細を扱っているからです(あなたが扱っているものに関係なく)。

少なくともCakePHPに関しては:

  1. はい

  2. データまたはデータ操作を扱うものはすべてモデル内にある必要があります。 CakePHPに関しては、単純なfind()メソッドはどうですか? ...他の場所で必要になる可能性のある「特別な」(つまり、「条件」の特定のセットを思い出す)何かを行う可能性がある場合、それはモデルのメソッド内にラップする良い言い訳です。

  3. 残念ながら、簡単な答えはありません。コードのリファクタリングは自然なプロセスです。時々あなたはただ行くことを目覚めさせます:「聖なるマカロニ...それはモデルにあるべきです!」 (多分あなたはそれをしません、しかし私は持っています:))

55
vladko

少なくとも次の2つの「テスト」を使用して、ロジックが適切な場所にあるかどうかを確認しています。

1)ユニットテストを作成する場合、テストを実行するための1つの「実際の」オブジェクト(=本番環境で使用しているオブジェクト)のみを作成するのは簡単で、一部の値オブジェクトを除いて、他の多くのオブジェクトを含めることはできません。テストを実行するために実際のモデルオブジェクトと実際のコントローラーオブジェクトの両方が必要な場合は、機能を移動する必要があるというシグナルになる可能性があります。

2)自問してみてください。これらのクラスを使用する別の方法を追加した場合、ほぼコピー&ペーストする方法で機能を複製する必要がありますか? ...それはおそらくその機能を移動する良い理由でもあります。

また興味深い: http://www.martinfowler.com/bliki/AnemicDomainModel.html

19