ファットモデル/シンコントローラーvs.サービスレイヤー[クローズ]


83

私は長年.Netを使用してエンタープライズアプリケーションを開発してきました。私のアプリには通常、SQLDBテーブルにマッピングするエンティティを含むドメインモデルがあります。リポジトリパターン、依存性注入、サービスレイヤーを使用しています。

最近、MVC 3プロジェクトに取り組み始め、どのロジックをどこに配置するかについて議論しました。シンコントローラー/ FATモデルアーキテクチャに出くわし、サービスレイヤーがどのように適合するのか疑問に思いました

オプション1-モデルがサービスと話し合う

コントローラはシンで、モデルのメソッドを呼び出します。モデルは、DBから自分自身をロードし、リポジトリまたはサービスと通信する方法を「知っています」。たとえば、customerModelにはLoad(id)メソッドがあり、顧客とGetContracts()などの子オブジェクトをロードします。

オプション2-コントローラーがサービスと通信する

コントローラは、サービスにモデルオブジェクトを取得するように要求します。ロード/保存などのロジックはサービスレイヤーにあります。モデルは、データのみを含む純粋なエンティティモデルです。

特にエンタープライズアプリケーションについて話すとき、オプション1がより良い選択である理由は、私の経験から、関心の分離、モデルとコントローラーの可能な限り薄くし、ビジネスロジックを実行する特殊なサービス(DBインタラクションを含む)を使用するように指示されています。

良いリソースへのすべてのアドバイスと参照に感謝します。

回答:


94

これはすべて、アプリケーションの意図と要件によって異なります。

そうは言っても、これが「中規模」(地元のレストランではなく、Twitter / Facebookでもない)Webアプリケーションに対する私の提案です。

  1. リーンドメインモデリング

    ドライPOCOスタイルのオブジェクト。できればWebアプリケーションのMVCアーキテクチャを認識せず、特定の実装から可能な限り疎結合のままにします。おそらく、外部アプリケーションで使用するために再パック可能なクラスライブラリでさえ、WCFWebサービスを介したRESTAPIなどです。 )。

    MVCの「モデル」とは、コントローラーが認識しいるモデル、つまりビューを対象したモデルを最も正確に意味します

    小規模な(多くの場合チュートリアル)アプリケーションでは、「アプリケーション/ドメインモデルレイヤー」のエンティティモデルは、多くの場合、コントローラーがビューに送信するのと同じインスタンス化されたオブジェクトです。

    大規模なアプリケーションでは、開発者はMVVMアーキテクチャの信条を採用し、個別のビューモデルオブジェクトの使用を開始することがよくあります。コントローラーは、多くの場合、以下の見えないエンティティと連携する中間層サービスを呼び出します。このシナリオでは、MVCのMは最も正確にはビューモデルを意味します。

  2. 堅牢なサービスレイヤー

    これは肥満の論理を意味するのではなく、よく書かれた単一目的のサービスを意味します。モデル外のサービスでビジネスロジックをコーディングすることは、純粋な「OOP」よりも少し「手続き型」ですが、疎結合、テスト、および柔軟な展開(n層展開など)に大いに役立ちます。

    私の個人的な慣習では、POCOオブジェクトの動作モデリング(永続性メカニズム、低レベルの検証など)を考慮したデータレイヤーでサービスをコーディングし、より高いレベルのサービス(ビジネス/ワークフロー関数)をより近くでコーディングします。 MVCの仕組み。

  3. リーンコントローラー

    私のコントローラーは、プレイ(サービス)でもプレーヤー(エンティティモデルまたはビューモデル)でもないという点で、単なるコーチであることを確認しますが、誰がどのポジションでどのプレイを行うかを決定するだけです。私のコントローラーは2つのことをします:

    1. エンティティ/ドメインモデルと相互作用するコールサービス

    2. 適切なビューのビューモデルを準備します。

    認証/承認されたコントローラーアクションでさえ、注入されたサービス/属性を介して実行されます。


編集1:

これは、エンティティ/ドメインモデルが貧血である、または貧血である必要があることを意味するものではないことに注意してください。ORM、リポジトリと工場、検証または州の整備士は大歓迎です。それだけで適度な規模のアプリケーションのために、意味モデルMVCでは表しあなたのビューにハンドオフする、コントローラのために意味のモデルを

うまくいけば、この点が貧血データモデルアンチパターンであると信じているファウラー使徒たちを落ち着かせるでしょう。同時に、モデル化されたクラスに動作を含める方が純粋なOOPよりもわずかに手続き的な角度を反映してます。

「究極の真実」はありませんが、このパターンを使用すると、多くの再利用性とスケーラビリティを維持しながら、アプリケーションの構築、テスト、およびデプロイが簡単になります。


編集2:

とは言うものの、適度なサイズのアプリケーションであっても、(単語のオタクが作り上げた)設計よりもシステムはあまりにも一般的です。たとえば、ORMをリポジトリパターンでラップしてから、リポジトリを使用するサービスを作成します...これはすべて、関心の分離などに適していますが、プロジェクトで必要がない場合(すぐに必要になる可能性はほとんどありません))そのようなもの、それを構築しないでください。リポジトリをすべてスキップしたり、ORMに対してシンビジネスサービス(クエリクラスなど)を記述したり、コントローラーに直接リポジトリと通信させたりしても問題はありません。それはすべて規模に依存します。


編集3:

この説明とアドバイスは、ASP.NetのようなサーバーサイドMVCアーキテクチャのコンテキスト向けであり、KnockoutやBackboneのようなクレントサイドフレームワーク向けではないことに注意したいと思います。


11
これは、コントローラーがリポジトリーの知識を持っていないことを除いて、私が使用しているデザインパターンとほぼ同じです。コントローラーは、リポジトリーと対話するサービスとのみ対話します。
レスター2012年

2
@レスター私はそれをクリアするために編集しました。私の95%はそうではありません、アイデアはサービスがそうするということです。小さなアプリではやり過ぎかもしれませんが、誰でも良い習慣であり、IoCコンテナで保守するのがはるかに簡単です
one.beat.consumer 2012年

1
+1 @ one.beat.consumer:これは私がプロジェクトで採用しているのと同じアプローチです...ルールについて純粋すぎると、ソリューションが複雑になりすぎて、実際の実績のあるソリューションからより多くのメリットを得ることができます。 GOFパターンに完全には従いません
themarcuz 2012年

7
MVCの@ivowibloモデルは、コントローラーが準備してビューに渡すデータモデルです。これが、「アプリケーションモデル」(ドメインモデル、モデルレイヤー、ラベル付けしたもの)がMVCライブラリを完全に認識できない理由であり、ソリューションの外部の個別に分散されたシステムに存在する場合でも同様です。MVCでは、リクエストは単にコントローラーにルーティングされます。コントローラは、ビューモデル(プレゼンテーション層のデータ)をアセンブルします。そのモデルは、あなたの永続性力学に使用したのと同じオブジェクトのインスタンス、貧しい人々の練習かもしれないですが、それがもしされて許可され、何の排他的な定義がないことを意味します。
one.beat.consumer 2012年

2
+1 for MVCの「モデル」は、コントローラーが認識しているモデル、つまりビューを対象としたモデルを最も正確に意味します。
ルイスダミム2012

16

先に進んですべてをどこに置くかを議論する前に、MVCについてもう少し知る必要があります。さて、あなたがパターンに従いたいのなら。それ以外の場合は、今すぐ読むのをやめることができます。

パターンは非常に大まかに定義されています。コントローラ、ビュー、またはモデルがどのように見えるか、またはそれらがどのように構造化されるべきかについては何も述べていません。このパターンは、パーツを分離する必要があり、パーツが互いにどのように相互作用するかを示しているだけです。それで、それらが何であるかについてもう少し見てみましょう(私の解釈)。

MVC

モデル モデルは何でもかまいません。これは、Webサービス、リポジトリ、サービスクラス、または単にドメインモデルの場合があります。モデルは、必要な情報を取得するために使用されるすべてのものです。「モデル」を単一のオブジェクトではなくレイヤーと見なします。

コントローラー コントローラーは接着剤です。モデルから情報を取得し、それをビューに適合させます。その逆も同様です。

ビュー ビューは、ユーザーに表示されるもののみをレンダリングする必要があります。

モデルとビューモデルを混同しないように注意してください。Microsoftは、実際には「Model」フォルダに「ViewModels」という名前を付けているはずです。「モデル」からの情報をビューで直接使用することはありません。そうしないと、ビューが変更された場合はモデルを変更する必要があり、その逆も同様です。

答え

モデルはビューモデルではなく、レイヤーです。モデル内のすべては、ビューに必要な情報をフェッチするために使用されます。コントローラはその情報を取得し、それを単一のビューモデルに配置します。

単一のコントローラーアクションは、「モデル」への1つまたは複数の呼び出しを使用して、ビューに必要な情報を組み立てることができます。

つまり、保守と拡張が簡単なアプリケーションを入手したい場合は、2番目のオプションが最も適切です。

サービスレイヤーは必要ない場合があることに注意してください。コントローラから直接OR / Mを呼び出すことができます。ただし、コードを複製したり、ファットコントローラーを取得したりする場合は、ロジックをサービスレイヤーに移動するだけです。適切なビューモデルを使用しているため、コントローラー以外はその変更の影響を受けません。


3
ASP.NETMVCが代わりにASP.NETModelView ViewControllerという名前になっているといいのですが。それは恐ろしい名前ですが、少なくともその本当の意味を伝えるでしょう:)
Hector Correa 2012年

ASP.NET MVCを使用した後でも、モデルがビューモデルを意味しないことに気付くのにしばらく時間がかかりました。
レスター2012年

@ one.beat.consumer:モデルについての私のポイントは、それは何でもよいということでした。それはただの層です。アプリケーションに合わせて作成します。ASP.NET MVCのモデルはビューモデルである、またはVMとモデルは同じであると多くの人が考えているので、私はそのように言います。
jgauffin 2012年

私はその質問に答えると思います。customerModel彼が質問で話しているときの私の解釈は、ビューモデルです。彼がそうではないことを理解していれば、答えはより明白です。
jgauffin 2012年

2
@jgauffinセマンティクスはここで重要です-MVCでは「モデル」「モデルレイヤー」を意味しません。それは、コントローラーがビューに渡すのに適したモデルオブジェクトを意味するだけです。大規模なアプリケーションでは、MVCアーキテクチャは、モデル/データレイヤー、またはそれを呼び出すために選択したものを認識しないことがよくあります。私の編集した回答は、この混乱を説明しようとしています...主にアプリが小さい場合、モデルとビューモデルをさらに分離する必要がないことが多いため、人々はモデルをマークアップして、コントローラーにリポジトリを使用させる傾向があります。フルサイズのアプリでは、これはめったに起こりません。
one.beat.consumer 2012年

0

オプション1:モデル==サービスと考えることができます。モデルはビジネス層でもあります。

オプション2は、貧血ドメインモデルのアンチパターンです。 http://en.wikipedia.org/wiki/Anemic_domain_model


何かをアンチパターンと呼ぶには、もう少しコンテキストが必要であることに注意してください。多くのアプリケーションはドメインモデルを必要としません。なぜなら、それらが行うほとんどのことはCRUD操作だからです。
ルーキアン2013

ドメインモデルは「メタデータ」を含む単なるデータです。メタデータがない場合は問題ありません。あなたがその部分に正しいので、私は「アンチパターン」という言葉を削除しました。私は受け入れられた答えが本当に好きで、代わりに私自身がコメントされるべきでした。
imre L

0

オプション2は、Fat Stupid Ugly Controllersアーキテクチャとして説明されているものです(この式の作成者への参照)。このソリューションは、関心の分離を破るため、一般的にMVCの精神に反します。


1
public ActionResult FetchApple() { return View(_groceryService.GetApple("Granny Smith")); }あなたが私に尋ねればかなり痩せています。
one.beat.consumer 2012年

4
そのFSUCの記事を読んだところ、上記のオプション2と一致しません。FSUC作成者が提供する例は、すべての順序付けロジックがカプセル化されているサービスレイヤーの使用を示していません。代わりに、コントローラーにビジネスロジックがロードされていることを示しています。そして、コントローラー内にあるため、ビジネスロジックの再利用性は失われます。
Marvo 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.