web-dev-qa-db-ja.com

.NET MVCプロジェクトのアーキテクチャー/レイヤー化

中規模のMVC Webアプリケーションのアーキテクチャを計画する場合、レイヤーを可能な限り分離してテストしやすいように実装するにはどうすればよいですか? (基本的にベストプラクティスに従います)データアクセスとして最初にコードを使用しているとしましょう。

「ビジネスロジック」を何として定義し、どのようにデータレイヤーとやり取りするかについて、私は苦労しています。車両販売アプリケーションを例にとると、ビジネスロジックは、特定の車両の税帯の計算、ガロンあたりのマイル統計の比較などのタスクを実行するクラスでしょうか。ビジネスエンティティ(Cars、Vans、Motorcyclesなど)については、これらをDataContextクラスと共にデータレイヤーに配置します。

また、ビジネスではなくアプリケーションロジックを構成するものは何ですか。セッション/ユーザー入力の検証などを推測しているのでしょうか。

そのため、たとえば、車のコントローラーは、タイプおよび最適なmpgでフィルターされた上位10台の車をリストするアクション/ビュー結果を返す場合があります。たとえば、コントローラにICarRepository 'carRepo'を注入したとしましょう(リポジトリパターン/ DIを使用)。アクションメソッドのパラメータから車をフィルタリングします。 var cars = carRepo.getCarsByType("hatchback");

そこで、リポジトリを使用してデータアクセスの知識をコントローラーから除外し、ドメインモデルを使用してビジネスロジックをコントローラーから除外しました-var result = new MpgCalculator(cars); -DBからエンティティをロード/フィルタリングするだけでなく、最高の燃料効率を計算するために追加のロジックを実行する必要があるため、電卓クラスが必要だとしましょう。これで、ビューをレンダリングするためのデータセットがあり、リポジトリを使用してデータアクセスレイヤーから取得し、ドメイン固有のオブジェクトを処理して、そのデータに対してビジネス関連のタスクを実行します。

ここで間違いをしていますか?それでもリポジトリパターンを使用する必要がありますか、それともORMを分離してテストするためにインターフェイスに対してコーディングするだけですか?このトピックでは、具体的なデータアクセスクラスdbcontextがデータレイヤーにあるので、インターフェイス定義をドメイン/ビジネスレイヤーに入れる必要があります。つまり、データアクセステクノロジーが変更されても、他のレイヤーは影響を受けません。

これまでに調べたことから、私の構造は次のようになります。

MVCインターネットアプリケーション->標準のインターネットプロジェクト-ここにあるモデルはViewModelです

ドメイン/ビジネスレイヤー->関連するビューに渡す前にコントローラーがデータレイヤーのドメインエンティティを処理するために使用できるビジネス固有のクラス/モデル

リポジトリの抽象化が必要ですか?->特にORMを使用している場合、これについて多くの議論が聞こえます

データレイヤー->エンティティクラス(Car、Van、Motorcycle)、DbContext-具体的なデータアクセステクノロジーレイヤー

11
Michael Harper

質問には多くの可動部分があり、多くの概念に触れていますが、中規模から大規模のMVCアプリケーションについて考えるときの基本的なアドバイスを次に示します。

プレゼンテーション<--->ビジネスロジック<--->データアクセス

まず、アプリを "MVCアプリケーション"としないのが最適です。これは、MVCパターンをプレゼンテーションコンポーネントとして使用するアプリケーションです。このように考えると、ビジネスロジックの懸念とプレゼンテーションの懸念を区別するのに役立ちます。おそらく、小規模なアプリケーションがデータベースアクセスまですべてをMVC構造に積み重ねることは問題ありませんが、中規模から大規模なアプリケーションではすぐに受け入れられなくなります。

MVC(プレゼンテーション)

アプリでは、ASP.NET MVCコンポーネントは、表示のためのビジネスデータの変換(モデル)、ユーザーインターフェイスの表示(ビュー)、ルーティング、認証、承認、要求の検証、応答の処理などの通信の問題、および(コントローラ)のように。他のことを行うコードがある場合、それはMVCコンポーネントに属していません

Repository/ORM(Data Access)

また、アプリでは、データアクセスレイヤーは永続データの取得と保存に関係する必要があります。通常、これはリレーショナルデータベースの形式ですが、データを永続化する方法は他にもたくさんあります。永続データを読み取ったり格納したりしていないコードがある場合、その場合、データ層に属しません。私は以前にSO-で ORM /リポジトリディスカッションに関する私の考え を共有しましたが、要約すると、いくつかの理由で、ORMをリポジトリと同じものとは見なしていません。

ビジネスロジック

これで、プレゼンテーションレイヤー(MVC)とデータレイヤー(リポジトリまたはORM)ができました。それ以外はすべてビジネスロジックレイヤー(BLL)です。取得するデータを決定したり、複雑な計算を実行したり、ビジネス上の決定を行ったりするすべてのコードがここにあるはずです。私は通常、ビジネスロジックを「サービス」の形式で編成します。これは、プレゼンテーションレイヤーが要求された作業を実行するために呼び出すことができます。私のドメインモデルはすべてここにあります。

あなたのアプローチ

ここで、あなたのアプローチが少し崩れます。 MVCコントローラーをリポジトリからデータを取得する場所として記述し、MPGCalculatorを呼び出していくつかの作業などを行います。コントローラーにこれを行わせることはありません。 、しかし代わりにこれらすべてをBLLのサービスに委任します。

言い換えれば、リポジトリとMPGCalculatorをコントローラに挿入しないので、コントローラに大きな責任が与えられます(前述のcontrollerのすべてをすでに処理しています)。代わりに、BLLのサービスですべてを処理し、結果をコントローラーに返します。コントローラーは結果を正しいモデルに変換し、それを正しいビューに渡すことができます。コントローラーにはビジネスロジックが含まれておらず、コントローラーに注入されるのは適切なBLLサービスだけです。

このようにすることは、ビジネスロジック(たとえば、一連の車両を与えられ、MPGを計算し、最悪にソートする)が、プレゼンテーションや永続性の問題から独立していることを意味します。それは通常、データ永続化戦略もプレゼンテーション戦略も知らないか気にしないライブラリにあります。

26
Eric King

すべてがあなたの構造に合っているようです。 MVCのモデルは "ViewModels"であり、コントローラーがドメインレイヤーと通信していると私が確信している唯一のことです。コントローラーを使用してドメインレイヤーにアクセスし、「ViewModels」を使用して複数のドメインエンティティからの特定のビューの情報をビュー固有のコンパイルとして特定のビューに適用する場合、これは理にかなっていると思います。それがあなたがやっていることなら、おそらく大丈夫です。

MVCアプリケーションでドメインレイヤーを完全に抽象化する必要がある場合は、それを完全に抽象化する必要があるという考え方があります。個人的には、エンタープライズアプリケーションでそれを行うことを考えると、私はひどい精神的苦痛を引き起こします。

データレイヤーへのアクセスを管理するためにリポジトリパターンを使用することをお勧めします。これにより、テスト容易性と柔軟性が向上します。最も劇的な変更を加える傾向があるのは、UIとデータベースの2つです。データベースから直接取得している情報の一部が変更され、データベース呼び出しではなくサービス呼び出しから取得する必要がある場合や、一部の情報が別の.edmxを必要とする別のデータベースに移動した場合を想像してください。ファイル。リポジトリパターンは、これをサポートする抽象化を提供します。

0
wpenberthy