web-dev-qa-db-ja.com

太ったモデルと細いコントローラーは、神のモデルを作成するように聞こえます

ファットモデルとスキニーコントローラーアプローチを支持する多くのブログを読んでいます。 Rails camp。結果として、ルータは基本的に、どのコントローラでどのメソッドを呼び出すべきかを判断し、すべてのコントローラメソッドはモデルの対応するメソッドを呼び出してからビューを表示するだけです。ここで、私には理解できない2つの懸念があります:

  1. コントローラーとルーターは、ルートに基づいて神のようなモデルのメソッドを呼び出す以外に、実際にはそれほど多くの異なるタスクを実行していません。
  2. モデルはやり過ぎです。電子メールの送信、関係の作成、他のモデルの削除と変更、タスクのキューイングなど。基本的には、データのモデリングと処理に関係するかどうかに関わらず、すべてを実行することになっている神のようなオブジェクトがあります。

どこで線を引きますか?これは単に神のパターンに陥っていませんか?

87
Jungle Hunter

MVCデザインパターンの定番としてRailsを見るのは最良のアイデアではないかもしれません。このフレームワークは、いくつかの固有の欠点を伴って作成されました(私は post )とコミュニティはフォールアウトの対処を始めたばかりで、DataMapper2 development を最初の主要なステップとして見ることができます。

いくつかの理論

そのアドバイスをする人々は、非常に一般的な誤解に苦しんでいるようです。それで、私はそれを片づけることから始めましょう:現代のMVCデザインパターンのモデルはクラスでもオブジェクトでもありません。モデルはレイヤーです。

MVCパターンの背後にあるコアアイデアは 懸念の分離 であり、その最初のステップはプレゼンテーションレイヤーとモデルレイヤーの分割です。プレゼンテーションレイヤーがコントローラー(インスタンス、ユーザー入力を処理する)、ビュー(インスタンス、UIロジックを処理する)、およびテンプレート/レイアウトに分割されるように、モデルレイヤーも同様です。

モデルレイヤーの主要な部分は次のとおりです。

  • ドメインオブジェクト

    ドメインエンティティ、ビジネスオブジェクト、モデルオブジェクトとも呼ばれます(混乱を招くだけなので、後者の名前は嫌いです)。これらの構造は、人々が誤って「モデル」と呼ぶものです。それらは、ビジネスルール(ドメインロジックの特定のユニットのすべての数学と検証)を含む責任があります。

  • ストレージの抽象化:

    通常、 data mapper パターンを使用して実装されます(この名前を悪用した ORMs と混同しないでください)。これらのインスタンスは通常、ドメインオブジェクトへの情報の格納と取得をタスクとしています。いくつかの形式のストレージ(DB、キャッシュ、セッション、Cookie、/ dev/null)があるように、各ドメインオブジェクトは複数のマッパーを持つことができます。

  • サービス:

    アプリケーションロジック(つまり、ドメインオブジェクト間の相互作用、およびドメインオブジェクトとストレージ抽象化間の相互作用)を担当する構造。これらは、プレゼンテーション層がモデル層と対話するための「インターフェース」のように動作する必要があります。これは通常、Railsのようなコードではコントローラーで行われます。

これらのグループ間のスペースにある可能性のあるいくつかの構造もあります: DAOsunits of work 、および repositories

ああ...そして、(Webのコンテキストで)MVCアプリケーションとやり取りするserについて話すとき、それは人間ではありません。 「ユーザー」は、実際にはWebブラウザーです。

それでは、神々はどうですか?

恐ろしくモノリシックなモデルを使用する代わりに、コントローラーはサービスと対話する必要があります。ユーザー入力から特定のサービスにデータを渡します(たとえば、MailServiceまたはRecognitionService)。このようにして、コントローラーはモデル層の状態を変更しますが、それは明確なAPIを使用して、内部構造を混乱させることなく行われます(漏れやすい抽象化の原因となります)。

このような変更は、即時の反応を引き起こすか、ビューインスタンスがモデルレイヤーから要求するデータにのみ影響するか、その両方です。

各サービスは、任意の数(ただし、通常はほんの一握りです)のドメインオブジェクトとストレージの抽象化と対話できます。たとえば、RecogitionServiceは記事のストレージ抽象化についてあまり気にすることはできません。

最後に

このようにして、任意のレベルで単体テストが可能で、結合が低く(正しく実装されている場合)、明確に理解できるアーキテクチャを持つアプリケーションを取得できます。

ただし、心に留めておいてください:MVCは小さなアプリケーション向けではありません。 MVCパターンを使用してゲストブックページを作成している場合は、間違っています。このパターンは、大規模なアプリケーションでlaw and orderを強制するためのものです。

PHPを第一言語として使用している人にとっては、 この投稿 が関連している可能性があります。これは、コードのスニペットを含むモデル層の少し長い説明です。 。

130
tereško

「モデル」クラスの実装が不十分である場合、懸念事項が関係します。モデルクラスは、電子メール(インフラストラクチャタスク)を実行しないでください。

本当の問題は、MVCのモデルが何を意味するかです。いくつかのメソッドを持つPOCOクラスに制限されていません。 MVCのモデルとは、データとビジネスロジックを意味します。クラシックコアPOCOモデルのスーパーセットとして扱います。

View ==== Controller ==== Model ---> Business Process layer-> Core models

インフラストラクチャアセンブリとデータアクセスレイヤーをスローし、インジェクションを使用してそれをBPLに渡すと、プロセスは意図したとおりにMVCを使用します。

BPLは、UoW /リポジトリパターンを呼び出し、ビジネスルールを実行し、注入されたオブジェクトまたはインターフェイスパターンを介してインフラストラクチャ機能を呼び出します。

したがって、コントローラーをスキニーに保つという推奨事項は、従来のCoreモデルの「person」クラスに50個のメソッドがあり、Emailを直接呼び出すことを意味するものではありません。これは間違っていると考えるのは正しいことです。

直接呼び出された場合、Infrastructureクラスをインスタンス化してBPLまたはコアレイヤーに挿入するために、コントローラーが必要になる場合があります。ビジネスレイヤ、または少なくともクラシックオブジェクトモデルクラス全体で呼び出しを調整するクラスが必要です。とにかくそれは私の「ビュー」です;-)

MVCの一般的な解釈については、wikiの説明 http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

MVCの「M」について語る小さなブログ。 http://www.thedeveloperday.com/skinny-controllers/

5
phil soady