web-dev-qa-db-ja.com

作業単位とリポジトリパターンは大きなプロジェクトに非常に役立ちますか?

ASP.NET Webforms + EF4を使用して新しいWebプロジェクトを開始しています。このチュートリアルに従って、作業単位パターンでリポジトリパターンを適用しようとしています: http://www.dotnetage.com/publishing/home/2011/07/05/6883/the-repository-pattern -with-ef-code-first-dependeny-injection-in-asp-net-mvc3.html

私はアイデアを得たと思いますが、私の質問は、モデルで新しいオブジェクトを作成するときに、作業単位のIDALContextでそのオブジェクトも定義する必要があるということです。それは急速な発展のための手がかりではありませんか?また、複数の開発者と協力していて、他の開発者にDALを見せたくない場合、これをどのように管理できますか?私が理解しているこのパターンでは、モデルで新しいオブジェクトを作成するときに、このチュートリアルのIDALContextでもオブジェクトを定義する必要があるためです。すみません、これでとても混乱しています。

25
mehmetserif

Martin Fowlerは、リポジトリの役割を次のように説明しています。「リポジトリは、ドメインとデータマッピングレイヤーの間を仲介し、メモリ内のドメインオブジェクトコレクションのように機能します」。 Entity Framework 4.1が公開するものisその意味でのリポジトリ。また、EFには作業の統一が組み込まれています。したがって、私のアドバイスは、質問で言及したブログ記事を無視することです。

このようなコードは、役に立たない、または価値がないだけでなく、コードに利点が追加されるのではなく依存関係があるため、危険です。

public interface IUnitOfWork:IDisposable
{
    int SaveChanges();
}

public interface IDALContext : IUnitOfWork
{
    ICategoryRepository Categories { get; }
    IProductRepository Products { get; }
}

ドメイン層とデータマッピング層の間を仲介する抽象化を持っているという質問に答えるには、インメモリドメインオブジェクトコレクションのように機能することが「大きな」プロジェクトにとって必須です。また、内部にUnitOfWorkメカニズムがあると、ビジネスロジックをアクセスからデータアクセスの抽象化に切り離すのに役立ちます。

TL; TR;リポジトリとUnitOfWorkは役に立ちますが、特定のブログ投稿のように適用しないでください。

19
saintedlama

さて、最初の質問は次のようになりますリポジトリまたは作業単位パターンが必要なのはなぜですか?コントローラーからEFコンテキストを使用して、直接書き込む能力をフルに活用できませんでした。クエリが必要で、データを返しますか?
回答:可能ですが、背後にある本当の目的は、テスト容易性、したがってより高品質でより保守しやすいコードです。データアクセスを分離して1つの場所に集中させると、テスト中にモックアウトできます。これにより、データストアに効果的に書き込むことなく、コントローラー内で定義されたロジックをunitテストできます。

作業単位を開始する前に、リポジトリパターンを確認してください。これは基本的に、特定のエンティティのデータアクセスを抽象化します。したがって、Filter()、All()、Update(..)、Insert(..)、Delete(...)、最後にSave()などのメソッドを定義します。実際、これらのほとんどは_BaseRepository<TEntity>_クラスに非常に簡単に抽象化できるため、最終的には、特別な動作を伴うまれなケースで新しいリポジトリを作成する必要があります。それ以外の場合は、BaseRepository<Person> personRepo = new BaseRepository<Person>()またはBaseRepository<Address> addressRepo = new BaseRepository<Address>()などになります。

なぜ作業単位が必要なのですか?
作業単位は、通常はHttpリクエストごとにWeb環境で、特定のサイクル中に実行されるすべての操作を表します。つまり、新しいリクエストが入力されると、新しい作業ユニットをインスタンス化し、新しいものを追加し、更新または削除してから、.save()または.commit()を呼び出して変更を「コミット」します。 ..なんでも。実際、Entity Framework DbContext(またはObjectContext)を詳しく見ると、それらはすでにある種の作業単位を表しています。
ただし、コントローラークラスにEFコンテキストを含める必要がないため(テスト容易性を忘れないでください)、さらに抽象化する場合は、リポジトリをグループ化して確実にするためのUoWを作成します。すべてが同じEFコンテキストインスタンスを共有します。後者は、DIコンテナ(依存性注入コンテナ)でも実現できます。

あなたの質問へ:それは大きなプロジェクトで役に立ちますか?
間違いなく、特にbigプロジェクトでは。責任を分離し(データアクセス、ビジネスロジック、ドメインロジック)、テスト可能にすることがすべてです。

99
Juri

ソフトウェアデザインパターンは、適切なコンテキストで特定の問題を解決するように設計されており、不適切に使用すると、値を提供せずに余分な不必要な複雑さをもたらします。

では、リポジトリパターンが解決しようとしている問題は何ですか?

1-重複クエリロジックの最小化:大規模なアプリケーションでは、いくつかの場所で多くの複雑なLINQクエリが重複している場合があります。その場合は、リポジトリパターンを使用してこれらのクエリをカプセル化し、重複を最小限に抑えることができます。

2-関心の分離の改善:複雑なクエリを想像して、特定のカテゴリで最も売れているコースを取得します。これには、積極的な読み込み、参加、グループ化、フィルタリング、等.

このような大規模で複雑なクエリをサービス/コントローラーに実装すると、サービス/コントローラーが太くなることになります。これらのクラスは、ノイズの多いスタブを大量に必要とするため、単体テストが困難になります。単体テストは長く、太く、保守できなくなります。

この問題に直面している場合は、リポジトリパターンの使用を検討してください。この例では、複雑なクエリをカプセル化して、リポジトリで最も売れているコースを取得できます。

courseRepository.GetTopSellingCourses(int categoryId, int count);

このようにして、サービス/コントローラーは、積極的な読み込み、参加、グループ化などを処理しなくなります。代わりに、リポジトリに委任されます。積極的な読み込み、参加、グループ化などはクエリロジックであり、サービスやプレゼンテーション層ではなく、データアクセス層に属していることを忘れないでください。

3-アプリケーションアーキテクチャを永続化フレームワークから切り離す:アプリケーションでEntity Frameworkクラス(DbContext、DbSetなど)を直接使用する場合、アプリケーションは次のようになります。 EntityFrameworkと緊密に結合されています。将来、別のO/RMに切り替える予定がある場合、または別のモデルを持つ新しいバージョンのEntity Frameworkに切り替える場合でも、アプリケーションの多くの部分を変更する必要があり、これによりアプリケーションに新しいバグが発生する可能性があります。リポジトリパターンを使用して、アプリケーションアーキテクチャをEntityFrameworkなどの永続化フレームワークから切り離すことができます。このようにして、アプリケーションへの影響を最小限に抑えながら、別のO/RMに自由に変更できます。

詳細については、このビデオをチェックしてください。

https://youtu.be/rtXpYpZdOzM

5
Mosh

代わりに「コマンド/クエリオブジェクト」を検討する必要があります。この領域の周りに興味深い記事がたくさんありますが、ここに良い記事があります。

https://rob.conery.io/2014/03/03/repositories-and-unitofwork-are-not-a-good-idea/

コマンドごとに1つのコマンドオブジェクトに固執して単純なトランザクションを有効にし、作業単位パターンの複雑さの必要性を回避します。

ただし、クエリごとのクエリオブジェクトがやり過ぎだと考えている場合は、100%正しい可能性があります。多くの場合、「FooQueries」オブジェクトから始めることを選択する場合があります。これは基本的にリポジトリですが、クエリ専用です。 「Foo」は、DDDの意味での「ドメイン集約」である可能性があります。

後で価値のある個々のクエリオブジェクトが見つかるかもしれません。

ほとんどの場合と同様に、システムごとに検討する必要があります。

1
Darren