web-dev-qa-db-ja.com

MVC + SOAアーキテクチャでは、ビジネスロジックをモデルに配置する根拠は何ですか?

Webアプリケーションを作成するとき、コントローラーにビジネスロジックを配置します。これは私の小さなアプリ開発チームにとってはうまく機能しました。私たちのアプリケーションは確実に実行され、うまく機能し、コードの保守も簡単です。私のデザインの説明については、以下を参照してください。

私のアーキテクチャとは対照的に、私がプログラミングフォーラムで見つけたアドバイスは、通常、ビジネスロジックをモデルに配置することを推奨しています。 なぜを理解したいのですが。

MVC + SOAアプリケーションを構築した経験に基づいて、コントローラーにロジックを配置することに対して警告し、モデルにロジックを配置することを推奨するのはなぜですか?理論的根拠は何ですか?私のデザイン?

私のデザインは Refit 、タイプセーフREST C#のプロキシ)の使用に影響されていることを認めます。ビジネスロジックを配置したくない理由の1つモデル(またはエンティティ)では、サービスインターフェイスとエンティティをコントラクトで定義しているためですDLLサービス(WebAPI)とクライアント(MVC Webサイトまたはコンソールアプリケーション)によって共有されます)。 (エンティティのLoad、Save、Approve、Rejectなどのメソッドを介して)データ永続性の詳細をクライアントに漏らしたい。

もう1つの影響は、これらの使い慣れた設計原則の矛盾を解決したいという私の願望から生じます。

  • エンティティは永続性にとらわれない必要があります。つまり、データベースやコンテンツ管理システム(CMS)にどのように保存されるかを知らないはずです。
  • MVCで、モデルにビジネスロジックを配置します。

「ビジネスロジック」にSQLまたはCMSステートメントが含まれている場合、原則は矛盾します。 「ビジネスロジック」にSQLまたはCMSステートメントが含まれていない場合、これはさらに別のレイヤーであるデータ転送オブジェクト(DTO)の導入を意味します。ああ、別の層ではありません。

また、最後の人気のパラダイムからの慣性により、オブジェクト指向(OO)デザイン(オブジェクトがすべて)がMVC + SOA=)の世界に忍び込んでいるように感じます。したがって、ビジネスを配置するためのアドバイスモデル内のロジック(オブジェクト)。

わかりました、十分な紹介。これが私のMVC + SOAアーキテクチャ(Microsoftスタックの場合)です:

MVC + SOA Design

MVC =モデルビューコントローラ、SOA =サービス指向アーキテクチャ

  • モデルは、コントローラーとビューの間でデータとUI(検証ルール、選択リストの選択など)を転送します。
  • ビューはモデルを受け取り、Razor構文を使用してHTMLをレンダリングします。
  • コントローラは(ASP.NETモデルバインディングを介して)モデルを受け取り、ローカル(2層アーキテクチャ)または外部(3層アーキテクチャ)のいずれかでビジネスロジックを実行します。
    • ローカルの場合、コントローラーはデータストア(データベースまたはファイル)と直接通信します。
    • 外部の場合、コントローラーはRefitプロキシーを使用して外部サービスと通信します(サービスはデータストアと直接通信します)。
  • ビューとモデルのビジネスロジックを最小限に抑えます。ビューは薄くなければならないため、「Razor」という名前です。
  • コントローラーのビジネスロジックを最大化します。
  • SOAとOO。の違いに注意してください。
    • SOAは、データとは別に、サービスコントローラーのロジックのカプセル化を強調しています。
      • HTTP/JSON/Refitインターフェースを介して公開されます。
      • モデルとエンティティは、検証とデータ転送に使用されます。
    • OOは、データの近くにあるオブジェクトのロジックのカプセル化を強調しています。

事業体

  • モデルと同様に、エンティティのビジネスロジックを最小化します。
  • モデルをエンティティから分離します。
    • モデルは、コントローラーとビューの間でデータとUIを転送します(上記を参照)。
    • モデルは、コントローラーとデータストアまたはサービスの間でデータを転送します。
      • これは over-posting を防ぎます(ハッカーはモデルのデフォルト値を上書きするために追加のフォームフィールドを追加します)。
      • これにより、各ページに異なるフィールドが必要な複数ページの段階的なフォームが容易になります。各ページのモデルを定義します。すべてのモデルのすべてのフィールドの結合=エンティティのプロパティのセット。
    • エンティティは、コントローラーとデータストアまたはサービスの間でデータを転送します。
    • エンティティにはUI(検証ルール、選択リストの選択肢など)が含まれていません。
  • エンティティはモデルを参照することはできません
  • モデルはエンティティを参照する場合があります。
    • コンストラクターはエンティティパラメーターを受け取り、エンティティプロパティをモデルプロパティにマップします。
    • ToEntity()メソッドはエンティティを作成し、モデルプロパティをエンティティプロパティにマップします。
  • 依存関係は一方向に流れます:

根拠

  1. エンティティから独立したオーバーポスト攻撃の防止とUIの柔軟性(複数のページにまたがる複雑なフォームまたは分割フォームとして存在)。
  2. 懸念の分離-モデルは検証ルールを指定し、UIとの間でデータを転送します。エンティティはサービスとの間でデータを転送し、コントローラーはタスクをシーケンスし、ビジネスロジックを適用します。
  3. バッキングサービスまたはデータストアの変更は、モデルまたはビューには影響せず、コントローラーにのみ影響します。
  4. サービスコントローラーのロジックは再利用可能です。HTTPエンドポイントを介して公開され、任意の言語で記述されたクライアントから呼び出すことができます。
  5. 私のRefit C#プロキシの使用は、AJAXを決して妨げません。実際、JWTトークンで保護されたサービスコントローラーへのjQuery呼び出しを介して、UIの更新を数多く行っています。
2
Erik Madsen

Model-View-Controllerパターンは、いくつかの基本原則に従うUIパターンです。

  1. ビューはユーザーインターフェースであり、コントローラーの前にある薄いベニアです。ビューにある必要がある唯一のロジック(つまり、「コードビハインド」)は、ユーザーとの対話に直接関係するロジックです。

  2. コントローラは、モデルの前にある薄いベニアです。スイッチヤードとして機能し、ビューからモデルへのリクエストを処理のために分路します。コントローラ内にあるべき唯一のロジックは、この通信を容易にするロジックです。

  3. モデルには、データアクセスレイヤー(この場合はDapperまたはEntity Framework Code)、リポジトリレイヤー(エンティティとCRUDメソッドを含む)、およびビジネスロジックを含む、アプリケーションに関するその他すべてが含まれます。レイヤー

このように説明された全体的なアーキテクチャは、次のようになります。

Database --> Data Access Layer --> Repository --> Business Layer --> Controller --> View

矢印は依存関係の知識の方向を示しています。例えばビューはコントローラーを認識していますが、その逆は認識していません。

ビジネス層は、CRUD /ビジネストランザクションコンバーターと考えることができます。左側では、リポジトリのエンティティを使用して、作成、読み取り、更新、削除を行います。右側では、ビジネスオペレーション(「請求書の印刷」や「顧客への請求」のようなもの)を、私が呼ぶView Modelオブジェクトを使用して説明します。これらのビューモデルオブジェクトは、UIを基になるデータ表現に接着するためにコントローラーが使用するものです。

私の例では、ビジネスレイヤーがコントローラーから抽象化されていることに注意してください。 これにより、同じビジネスレイヤーで異なるコントローラーを使用できます。

3
Robert Harvey