1. ホーム
  2. asp.net-mvc

[解決済み] MVCアプリケーションにおける「ビジネスロジック層」の位置づけは?

2023-05-02 04:50:48

質問

まず、ダサいと言われる前に、シンプルなタイトルにまとめるのに苦労しました。 別のタイトルは、「ドメイン モデルと 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 && ...) { %>

すべてが拡散し、オーバーレイヤーになっているように見えますが、このようにアーキテクトされたのには目的があるのです。 完璧でしょうか? しかし、コントローラからリポジトリを呼び出し、コントローラ、リポジトリ、およびモデルにビジネスロジックを混在させる過去のいくつかのデザインよりも、私はこれを好んでいます。