[解決済み] MVCアプリケーションにおける「ビジネスロジック層」の位置づけは?
質問
まず、ダサいと言われる前に、シンプルなタイトルにまとめるのに苦労しました。 別のタイトルは、「ドメイン モデルと MVC モデルの違いは何ですか」または「モデルとは何ですか」だったかもしれません。
概念的には、モデルはビューとコントローラで使用されるデータであると理解しています。 それ以上に、何がモデルを構成しているかについては、非常に多くの異なる意見があるようです。 ドメインモデルとは何か、アプリモデルとは何か、ビューモデルとは何か、サービスモデルとは何か、などなど。
たとえば、私が最近リポジトリパターンについて質問したとき、リポジトリはモデルの一部であるとはっきり言われました。 しかし、私は、モデルは永続性モデルおよびビジネスロジック層から分離されるべきであるという他の意見を読みました。 結局のところ、Repositoryパターンは具体的な永続化メソッドをモデルから切り離すことになっているのではないでしょうか? 他の人々は、ドメインモデルとMVCモデルの間に違いがあると言います。
簡単な例で考えてみましょう。 MVCのデフォルトプロジェクトに含まれるAccountControllerです。 私は、含まれている Account のコードは設計が悪い、SRP に違反している、などといった意見をいくつか読みました。 もし、MVC アプリケーションのための適切なメンバーシップ モデルを設計するとしたら、それはどのようなものでしょうか?
ASP.NETサービス(メンバーシッププロバイダー、ロールプロバイダーなど)をどのようにモデルから分離するのでしょうか? あるいは、まったくそうしないのでしょうか?
私が見るところ、モデルは純粋であるべきで、おそらく検証ロジックがあるのでしょうが、ビジネスルール(検証以外)からは分離されるべきです。 例えば、新しいアカウントが作成されたときに誰かに電子メールを送らなければならないというビジネスルールがあるとします。 私の考えでは、これはモデルにはふさわしくありません。 では、どこに属するのでしょうか?
どなたかこの問題に光を当てていただけませんか?
どのように解決するのですか?
私が行った方法は - それが正しいか間違っているかは言いませんが - 私のビューと、私のビューに適用されるモデルを持つことです。 このモデルには、データのアノテーションや検証ルールなど、ビューに関連するものだけが含まれています。 コントローラは、モデルを構築するためのロジックだけを格納します。 私は、すべてのビジネスロジックを格納するサービスレイヤーを持っています。コントローラはサービスレイヤーを呼び出します。 その先にはリポジトリ層があります。
私のドメインオブジェクトは、(実際にはそれ自身のプロジェクトの中で)別々に格納されています。 それらは独自のデータアノテーションと検証ルールを持っています。 私のリポジトリは、データベースに保存する前に、私のドメインのオブジェクトを検証します。 私のドメイン内のすべてのオブジェクトは、検証を組み込んだベースクラスを継承しているので、私のリポジトリは汎用的であり、すべてを検証します(そしてベースクラスを継承することを要求します)。
2つのモデルのセットを持つことはコードの重複であると思うかもしれませんし、ある程度はそうでしょう。 しかし、ドメインオブジェクトがビューに適切でない完全に合理的な例があります。
例としては、クレジットカードを扱うときです。支払いを処理するときにcvvを要求しなければなりませんが、cvvを保存することはできません(そうすると、5万ドルの罰金です)。 しかし、住所や氏名、有効期限の変更など、クレジットカードの編集もできるようにしたいのです。 しかし、あなたは編集するときに番号やCVVを私に教えるつもりはないでしょうし、私は確かにあなたのクレジットカード番号をページにプレーンテキストで置くつもりはないでしょう。 私のドメインには、新しいクレジットカードを保存するために必要なこれらの値がありますが、私の編集モデルにはカード番号やcvvは含まれていません。
多くのレイヤーに対する別の利点は、正しく設計されていれば、structuremapまたは別のIoCコンテナを使用して、アプリケーションに有害な影響を与えることなくピースを交換することができます。
私の意見では、コントローラのコードはビューを対象としたコードだけであるべきです。 これを表示する、あれを隠す、などです。 サービス層は、アプリのビジネスロジックを格納すべきです。 私は、ビジネスルールを簡単に変更したり、微調整したりできるように、すべてを1つの場所に置くことを好みます。 リポジトリレイヤーは、ビジネスロジックを排除し、データを照会してドメインオブジェクトを返すだけの比較的単純なレイヤーにします。 ビューモデルをドメインモデルから分離することで、カスタム検証ルールをより柔軟に設定することができます。 また、すべてのデータをビューの隠しフィールドに格納し、クライアントとサーバーの間を行き来する(あるいはバックエンドで再構築する)必要がありません。 ビューモデルは、ビューに関連する情報のみを格納し、ビューロジック用のブール値やカウント値、列挙型を持つようにカスタマイズすることができます。
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) &&
Model.SomeObject.SomeInt == 3 && ...) { %>
すべてが拡散し、オーバーレイヤーになっているように見えますが、このようにアーキテクトされたのには目的があるのです。 完璧でしょうか? しかし、コントローラからリポジトリを呼び出し、コントローラ、リポジトリ、およびモデルにビジネスロジックを混在させる過去のいくつかのデザインよりも、私はこれを好んでいます。
関連
-
[解決済み】@sectionスクリプトとは何か、何のために使うのか?
-
[解決済み] asp.net MVCの@RenderSectionとは?
-
[解決済み] Entity Framework Code Firstを使用して一意制約を設定することは可能ですか?
-
[解決済み] MVPとMVC、その違いは何ですか?
-
[解決済み] MVCで、文字列の結果を返すにはどうしたらいいですか?
-
[解決済み】djangoのビジネスロジックとデータアクセスの分離
-
[解決済み】サービスは常にDTOを返すべきですか、それともドメインモデルも返すことができますか?
-
[解決済み] MVCとRazorにおけるHtml.TextboxForとHtml.EditorForの相違点
-
[解決済み] NerdDinnerでASP.NET MVCでModelState.IsValidは何のために有効なのか?
-
[解決済み] ASP.NET MVC - ビジネスロジックはコントローラの中にあるべきか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】@sectionスクリプトとは何か、何のために使うのか?
-
[解決済み] Razor View throwing "The name 'model' does not exist in the current context".
-
[解決済み] ASP.Net MVCのmodelStateからすべてのエラーを取得する方法は?
-
[解決済み] MVCにおけるViewModelとは?
-
[解決済み] ASP.NET MVCでHTML-5のdata-*属性でダッシュを使用する方法
-
[解決済み】ASP.NET MVC 3 Razor - EditorForにクラスを追加する。
-
[解決済み】ViewModelのベストプラクティス
-
[解決済み] asp.net mvc: なぜ Html.CheckBox は追加の隠された入力を生成するのですか?
-
[解決済み] MVCのHTMLヘルパーで生成されたHTML要素にclass属性を追加するにはどうすればよいですか?
-
[解決済み] ASP.NET MVC: UrlHelperを使用するコントローラのユニットテスト