「ビジネスロジックレイヤー」はMVCアプリケーションのどこに適合しますか?


86

まず、誰かがだまされて叫ぶ前に、私はそれを簡単なタイトルに要約するのに苦労しました。別のタイトルは「ドメインモデルとMVCモデルの違いは何ですか?」だったかもしれません。または「モデルとは何ですか?」

概念的には、モデルはビューとコントローラーによって使用されるデータであると理解しています。それを超えて、モデルを構成するものについては多くの異なる意見があるようです。ドメインモデル、アプリモデル、ビューモデル、サービスモデルなどとは何ですか。

たとえば、リポジトリのパターンについて最近尋ねた質問で、リポジトリはモデルの一部であると空白で言われました。ただし、モデルを永続性モデルおよびビジネスロジック層から分離する必要があるという他の意見を読みました。結局のところ、リポジトリパターンは、具体的な永続化メソッドをモデルから切り離すことになっているのではないでしょうか。ドメインモデルとMVCモデルには違いがあると言う人もいます。

簡単な例を見てみましょう。MVCデフォルトプロジェクトに含まれているAccountController。含まれているアカウントコードの設計が不十分である、SRPに違反しているなど、いくつかの意見を読みました。MVCアプリケーションの「適切な」メンバーシップモデルを設計する場合、それは何でしょうか。

ASP.NETサービス(メンバーシッププロバイダー、ロールプロバイダーなど)をモデルからどのように分離しますか?それともあなたはまったく?

私の見方では、モデルはおそらく検証ロジックを備えた「純粋」である必要がありますが、ビジネスルール(検証以外)から分離する必要があります。たとえば、新しいアカウントが作成されたときに誰かにメールを送信する必要があるというビジネスルールがあるとします。それは私の見解では実際にはモデルに属していません。それで、それはどこに属しますか?

この問題に光を当てる気がある人はいますか?


1
そのため、4つの別々の質問をする必要があります。
ジョンファレル

3
キーワードは「ほぼ」です。これは実際には同じ質問ですが、おそらくサブ質問を使用して主要な質問を説明しています。
Erik Funkenbusch 2010

3
モデル-ビュー-コントローラー。reposirory / BL Viewですか?いいえ、コントローラーですか?いいえ、残っています:)?それはMVCであり、MSVCでも、MRVCでも、MBLVCでもありません。たった3つのレイヤーがあります。したがって、リポジトリはモデルの一部であり、BLはモデルの一部です。また、追加の分離を行うこともできますが、それはモデルレイヤーの内部で行われます。
LukLed 2010

3
@ LukeLed、@ bslm-そうではありません。MVCは、コントローラーまたはモデルが相互作用する他のレイヤーが存在できないとは言っていません。
ジョンファレル

3
@ LukLed-同意しない-MVCは単なるプレゼンテーション層パターンです。BLLやDALなどの他のレイヤーの構造には影響しません。
Cory House

回答:


69

私がそれを行った方法-そしてそれが正しいか間違っていると言っているわけではありませんが、私のビューを持ってから、私のビューに適用されるモデルを持っていることです。このモデルには、データの注釈や検証ルールなど、私の見解に関連するものしかありません。コントローラには、モデルを構築するためのロジックのみが格納されています。すべてのビジネスロジックを格納するサービス層があります。私のコントローラーは私のサービスレイヤーを呼び出します。それを超えて、私のリポジトリレイヤーがあります。

私のドメインオブジェクトは別々に格納されています(実際には、独自のプロジェクトにあります)。それらには、独自のデータ注釈と検証ルールがあります。リポジトリは、ドメイン内のオブジェクトをデータベースに保存する前に検証します。ドメイン内のすべてのオブジェクトは、検証が組み込まれている基本クラスから継承するため、リポジトリは汎用であり、すべてを検証します(基本クラスから継承する必要があります)。

2セットのモデルを持つことはコードの重複であると考えるかもしれません、そしてそれはある程度です。ただし、ドメインオブジェクトがビューに適していない場合は完全に合理的です。

適切な例は、クレジットカードを使用する場合です。支払いを処理するときにcvvを要求する必要がありますが、cvvを保存できません(そうすることで50,000ドルの罰金が科せられます)。ただし、住所、名前、有効期限の変更など、クレジットカードを編集できるようにしてほしい。しかし、あなたはそれを編集するときに私に番号やcvvを与えるつもりはありません、そして私は確かにあなたのクレジットカード番号をページにプレーンテキストで置くつもりはありません。私のドメインには、新しいクレジットカードを保存するために必要なこれらの値がありますが、私の編集モデルにはカード番号やcvvさえ含まれていません。

非常に多くのレイヤーのもう1つの利点は、正しく設計されていれば、構造マップまたは別のIoCコンテナーを使用して、アプリケーションに悪影響を与えることなくピースを交換できることです。

私の意見では、コントローラーコードはビューを対象としたコードのみである必要があります。これを表示したり、非表示にしたりします。サービスレイヤーには、アプリのビジネスロジックを格納する必要があります。すべてを1か所にまとめておくのが好きなので、ビジネスルールを簡単に変更したり微調整したりできます。リポジトリ層は比較的ダムである必要があります-ビジネスロジックがなく、データをクエリしてドメインオブジェクトを返すだけです。ビューモデルをドメインモデルから分離することにより、カスタム検証ルールに関してはるかに柔軟性があります。また、すべてのデータを非表示フィールドのビューにダンプして、クライアントとサーバー間で前後にプッシュする(またはバックエンドで再構築する)必要がないことも意味します。

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

すべてが分散して重なっているように見えますが、このように設計することを目的としています。完璧ですか?あんまり。しかし、コントローラーからリポジトリーを呼び出し、コントローラー、リポジトリー、およびモデルにビジネス・ロジックを混在させるという過去の設計よりも、私はそれを好みます。


エンタープライズMVCアプリケーションにあるもののほぼミラーです。N層アーキテクチャ。MVCアプリは、N層領域のビジネスオブジェクトおよびサービスとのみ対話します。
Ed DeGagne 2013年

ここでもほとんど同じです。定義、モデル、ビューモデル、DALなどの個別のプロジェクト。唯一の違いは、私のDALには、レポートまたはカスタム顧客ビューの複雑なデータの配布を最適化するためにWebのデータをフラット化するロジックが含まれていることです。私は今、WebファームとAzureクラウドを使用して、ルックアップテーブルなどのアプリケーションキャッシュに物事を保持することを躊躇しています。
Robert Achmann 2014

1
@Josh、サンプルプロジェクトのスクリーンショットを見せていただければ助かりますか?
shaijut 2015年

@Joshプロジェクトにデータベースがない場合はどうなりますか。サービス参照と相互作用します。すべてのドメインクラスとメソッドは、これらの参照から取得されます。このシナリオは階層構造に適していますか?
user6395764 2018

17

ビュー(ページ)、コントローラー、サービス、およびデータオブジェクト(モデル)がある従来のWebアプリケーション構造にMVC要素がどのように正確に適合するのか疑問に思うことがよくありました。あなたが言ったように、それの多くのバージョンがあります。

「貧血ドメインモデル」(主張されている)-アンチパターンを使用する、上記の広く受け入れられているアーキテクチャのために、混乱が存在すると思います。貧血データモデルの「反パターン性」についてはあまり詳しく説明しません(ここで説明するための私の努力を見ることができます(Javaベースですが、どの言語にも関連します))。しかし、要するに、それは私たちのモデルがデータのみを保持し、ビジネスロジックがサービス/マネージャーに配置されることを意味します。

しかし、ドメイン駆動型アーキテクチャがあり、ドメインオブジェクトが期待どおりであり、状態ロジックとビジネスロジックの両方を備えていると仮定しましょう。そして、このドメイン駆動の観点では、次のことが起こります。

  • ビューはUIです
  • コントローラはUIの入力を収集し、モデルのメソッドを呼び出して、UIに応答を返します。
  • モデルはビジネスコンポーネントであり、データを保持するだけでなく、ビジネスロジックも備えています。

私はそれがあなたの主な質問に答えると思います。リポジトリレイヤーのように、さらにいくつかのレイヤーを追加すると、事態は複雑になります。モデルに配置されたビジネスロジックによって呼び出す必要があることがよく提案されます(したがって、各ドメインオブジェクトにはリポジトリへの参照があります)。私がリンクした私の記事では、これはまったくベストプラクティスではないと主張しています。実際、サービス層を持つことは悪いことではありません。ちなみに、ドメイン駆動設計はサービス層を除外しませんが、それは「薄い」ものであり、ドメインオブジェクトを調整するだけであると想定されています(したがって、そこにはビジネスロジックはありません)。

広く採用されている貧血データモデルパラダイム(良いか悪いか)の場合、モデルはサービスレイヤーとデータオブジェクトの両方になります。


優れた点!1つの注意:サービスにも同じ混乱があります。少なくともサービスは、アプリケーションサービスとドメインサービスにすることができます。アプリケーションサービスは、リポジトリなどから情報を収集する単なる薄いラッパーです。ドメインサービスは、ドメインモデルの組み合わせ、またはドメインモデルに必ずしも適合しないものを使用するビジネスロジックを提供します。
Artru 2013

プロジェクトにデータベースがない場合はどうなりますか。サービス参照と相互作用します。すべてのドメインクラスとメソッドは、これらの参照から取得されます。このシナリオは階層構造に適していますか?
user6395764 2018

3

私の考えでは、

モデル-

ビジネスロジックを含めるべきではなく、プラグイン可能である必要があります(シナリオのようなWCF)。ビューにバインドするために使用されるため、プロパティが必要です。

ビジネスの論理 -

これは「ドメインサービスレイヤー」に配置する必要があり、完全に別のレイヤーです。また、ここに「アプリケーションサービス」というレイヤーをもう1つ追加します。

App Servicesはドメインサービスレイヤーと通信してビジネスロジックを適用し、最後にモデルを返します。

したがって、コントローラーはアプリケーションサービスにモデルを要求し、フローは次のようになります。

    Controller->Application Services(using domain services)->Model

2

MVCパターンとAsp.netフレームワークは、モデルがどうあるべきかを区別しません。

MS自身の例には、モデルの永続性クラスが含まれています。メンバーシップがモデルに含まれていることについてのあなたの質問。これは状況によって異なります。モデル内のクラスは何かによって所有されていますか?ログインしたユーザーと表示されるデータの間にリンクはありますか?編集可能な権限システムのデータ部分のフィルタリングはありますか?他の誰かがバックエンドサポートのためにそれまたは何かを見る必要があるので、誰があなたのドメインのオブジェクト部分を最後に更新または編集しましたか?

メールの例も異なります。ドメインイベントや特にイベントに精通していますか?メールを送信するための別のサービスはありますか?電子メールを送信する行為はドメインの一部ですか、それともシステムの範囲外のアプリケーションレベルの問題ですか?UIは、電子メールが正常に送信されたかどうかを知る必要がありますか?送信に失敗したメールは再試行が必要ですか?送信された電子メールの内容は、サポートまたはカスタマーサービスの要件のために保存する必要がありますか?

これらのタイプの質問は非常に広範で主観的ですが、私はあなたとあなたに投票したすべての人がこれを理解できるように答えています。

要件/タイムライン/リソースはすべて、システムのアーキテクチャに流れ込みます。収益モデルでさえ効果があります。また、撮影するパターンも考慮する必要があります。DDDは、モデルとしての永続性アプリケーションとは大きく異なり、その間のすべての傾斜は特定のアプリでも有効です。アプリをテストするために撮影していますか?これらすべてに効果があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.