私は、.Netを使用して長年エンタープライズアプリケーションを開発してきました。通常、アプリには、SQL DBテーブルにマッピングするエンティティを含むドメインモデルがあります。リポジトリパターン、依存性注入、およびサービスレイヤーを使用します。
最近、MVC 3プロジェクトの作業を開始し、どのロジックをどこに配置するかという議論がありました。 Thin Controller/FAT Modelアーキテクチャに出くわして、サービスレイヤーがどのように適合するか疑問に思いました
コントローラーは薄く、モデルのメソッドを呼び出します。モデルは、DBから自分自身をロードし、リポジトリまたはサービスと通信する方法を「知っています」。例えば。 customerModelにはLoad(id)メソッドがあり、顧客とGetContracts()などのいくつかの子オブジェクトをロードします。
コントローラーは、モデルオブジェクトを取得するようサービスに要求します。ロード/保存などのロジックはサービス層にあります。モデルは、データのみの純粋なエンティティモデルです。
私の経験では、懸念を分離し、モデルとコントローラーを可能な限り薄くし、ビジネスロジック(DBの相互作用を含む)を行う特別なサービスを提供することを教えてくれます。
良いリソースへのすべてのアドバイスと参照をありがとう。
これらはすべて、アプリケーションの意図と要件に依存します。
そうは言っても、「ミッドスケール」(地元のレストランではなく、Twitter/Facebookでもない)ウェブアプリケーションに対する私の提案です。
リーンドメインモデリング
できればWebアプリケーションのMVCアーキテクチャに無知なドライPOCOスタイルのオブジェクト。特定の実装から可能な限り疎結合のままにしておくことができます。たとえば、外部アプリケーションで使用するためにクラスライブラリを再パック可能、たとえばREST WCF Webサービス経由のAPI)。
MVCの「モデル」とは、最も正確にコントローラーが認識しているモデルを意味し、したがってViewを対象としたモデルを意味します。
小さな(多くの場合、チュートリアル)アプリケーションでは、「アプリケーション/ドメインモデルレイヤー」のエンティティモデルは、多くの場合、コントローラがビューに出荷する同じインスタンス化されたオブジェクトです。
大規模なアプリケーションでは、開発者は多くの場合MVVMアーキテクチャの原則を採用し、個別のビューモデルオブジェクトの使用を開始します。コントローラーは、多くの場合、以下の見えないエンティティと連携する中間層サービスを呼び出します。このシナリオでは、MVCのMはビューモデルを最も正確に意味します。
堅牢なサービスレイヤー
これは、obese logicではなく、よく書かれた単一目的のサービスを意味します。モデル外のサービスでビジネスロジックをコーディングすることは、純粋な「OOP」よりも「手続き的」ですが、疎結合、テスト、および柔軟な展開(n層展開など)に役立ちます。
私の個人的なプラクティスでは、データ層でサービスをコーディングします。これは、POCOオブジェクトの動作モデリング(永続メカニズム、低レベルの検証など)と、より近いレベルの高レベルのサービス(ビジネス/ワークフロー機能)を考慮していますMVCの仕組み。
リーンコントローラー
コントローラーが単にコーチであり、play(サービス)またはplayer(エンティティモデルまたはビューモデルではない)であることを確認します。 )、しかし、誰がどのポジションをプレーし、どのプレーをするかを単純に決定します。私のコントローラーは2つのことを行います。
エンティティ/ドメインモデルと相互作用するサービスを呼び出す
適切なビューのビューモデルを準備します。
認証/承認されたコントローラーアクションでさえ、注入されたサービス/属性を介して行われます。
編集1:
これは、エンティティ/ドメインモデルが貧弱であることを意味するわけではないことに注意してください。 ORM、リポジトリ、工場、検証、または状態の仕組みは大歓迎です。これは、中規模のアプリケーションの場合のみを意味し、MVCのModelは、Viewに引き渡すコントローラ用のモデルを表します。
この点で、貧血データモデルがアンチパターンであると信じているファウラーの使徒たちを落ち着かせることができれば幸いです。同時に、それはdoes OOPよりも少し手続き上の角度を反映しています。モデル化されたクラスに動作を含める方がより純粋です。
「究極の真実」はありませんが、このパターンを使用すると、多くの再利用性とスケーラビリティを維持しながら、アプリケーションを簡単に構築、テスト、デプロイできます。
編集2:
とはいえ、適度なサイズのアプリケーションであっても、システムの設計(Wordのオタクが作ったもの)が多すぎることはあまりにも一般的です。たとえば、ORMをリポジトリパターンでラップし、リポジトリを使用するサービスを作成します...これはすべて懸念事項などの分離に適していますが、プロジェクトが必要ない場合(そしてそうする可能性が低い場合)- soon require)そのようなこと、ビルドしないでください。リポジトリをすべてスキップしたり、ORMに対してシンビジネスサービス(クエリクラスなど)を書き込んだり、コントローラに直接話をさせたりすることには何の問題もありません。それはすべて規模に依存します。
編集3:
この説明とアドバイスは、KnockoutやBackboneなどのクライアント側のフレームワークではなく、ASP.Netなどのサーバー側のMVCアーキテクチャのコンテキストに関するものです。
先に進み、すべてを配置する場所について議論する前に、MVCについてさらに知る必要があります。まあ、パターンに従う場合。それ以外の場合は、今すぐ読むのをやめることができます。
パターンは非常に大まかに定義されています。コントローラ、ビュー、またはモデルがどのように見えるか、またはどのように構造化されるべきかを示すものは何もありません。このパターンは、パーツを分離する必要があることと、パーツが相互にどのように相互作用するかを単に示しています。それでは、それらが何であるかについてもう少し見てみましょう(私の解釈)。
モデルモデルは何でも構いません。 Webサービス、リポジトリ、サービスクラス、または単にドメインモデルになります。モデルは、必要な情報を取得するために使用されるすべてのものです。 「モデル」は、単一のオブジェクトではなくレイヤーとして考えてください。
コントローラーコントローラーは接着剤です。モデルから情報を取得し、それをビューに適合させ、逆も同様です。
Viewビューは、ユーザーが見るもののみをレンダリングする必要があります。
モデルとビューモデルを混同しないでください。マイクロソフトは、「モデル」フォルダーに「ViewModels」という名前を付けたはずです。ビューで「モデル」からの情報を直接使用しません。そうしないと、ビューが変更された場合にモデルを変更する必要があり、その逆もあります。
モデルはビューモデルではなく、レイヤーです。モデル内のすべてが、ビューに必要な情報を取得するために使用されます。コントローラはその情報を取得し、それを単一のビューモデルに入れます。
単一のコントローラーアクションは、1つまたは複数の「モデル」の呼び出しを使用して、ビューに必要な情報を組み立てることができます。
つまり、メンテナンスと拡張が簡単なアプリケーションを取得する場合は、2番目のオプションが最も適切です。
サービス層は必要ないかもしれないことに注意してください。コントローラから直接OR/Mを呼び出すことができます。しかし、コードを複製したり、太ったコントローラーを取得したりする場合は、単にロジックをサービスレイヤーに移動してください。適切なビューモデルを使用しているため、コントローラー以外はその変更の影響を受けません。
オプション1:モデル==サービスと考えることができます。モデルもISビジネス層。
オプション2は、Anemic Domain Modelアンチパターンです。 http://en.wikipedia.org/wiki/Anemic_domain_model
オプション2は、Fat Stupid Ugly Controllersアーキテクチャと呼ばれるものです( この式の作成者への参照 )。このソリューションは、懸念の分離を破るので、一般にMVC精神に反します。