17

私が見つけたリポジトリパターンの例はすべて、実装が何らかの形で異なっているようです。以下は、私が主に見つけた2つの例です。

interface IProductRepository
{
    IQueryable<Product> FindAll();
}

その後、通常、リポジトリと通信して FindAll() メソッドを呼び出し、文字「s」で始まる製品の検索や特定のカテゴリの製品のフェッチなどの操作を実行する別のレイヤーがあります。

私がよく見つけた他の例では、すべての検索メソッドをリポジトリに入れました

interface IProductRepository
{
    IEnumerable<Product> GetProductsInCategory(int categoryId);
    IEnumerable<Product> GetProductsStartingWith(string letter);
    IEnumerable<PromoCode> GetProductPromoCodes(int productId);
}

どの道を進むことをお勧めしますか? または、お互いの長所/短所は何ですか?

http://martinfowler.com/eaaCatalog/repository.htmlを読んだ私の理解から、最初のアプローチはこれを最もよく反映しているようです?

4

5 に答える 5

16

最初のものはひどいです。神オブジェクトIQueryableのようなものです。(すべてのOR / Mの中でも)100%完全な実装を見つけるのは本当に難しいです。ORMを使用する代わりに、直接公開することができます。そうしないと、リークのある抽象化レイヤーが作成される可能性があります。

Joelはそれを最もよく言います(テキストはウィキペディアの記事からのものです):

Spolskyの記事では、ほとんどの場合に機能する抽象化の多くの例に注意を促していますが、根本的な複雑さの詳細を無視できないため、抽象化自体によって単純化されるはずのソフトウェアに複雑さをもたらします

Joelsのブログエントリ

2番目のアプローチは、実装がはるかに簡単で、抽象化をそのまま維持できます。

アップデート

リポジトリを変更する理由が2つあるため、リポジトリは単一責任原則に違反しています。1つはProductsAPIが変更された場合で、もう1つはPromoCodeAPIが変更された場合です。次のような2つの異なるリポジトリを使用する必要があります。

interface IProductRepository
{
    IEnumerable<Product> FindForCategory(int categoryId);
    IEnumerable<Product> FindAllStartingWith(string letter);
}

interface IPromoCodeRepository
{
    IEnumerable<PromoCode> FindForProduct(int productId);
}

変更点:

  • Find私は、複数のアイテムが返されるときとGet、単一のアイテムが返される場合からメソッドを開始する傾向があります。
  • メソッド名が短い=読みやすい。
  • 単一責任。リポジトリを使用するクラスが依存関係に対して何を持っているかを判断する方が簡単です。

明確に定義された小さなインターフェースにより、SOLID原則の違反を簡単に見つけることができます。これは、原則が破綻したクラスはコンストラクターを肥大化させる傾向があるためです。

于 2012-04-17T11:34:53.943 に答える
1

コンセンサスが構築されています:ずっと2番目のオプション。IQueryableでクエリロジックがいたるところにリークしていることを除けば、それを正しく実装することの難しさは別として、テストしてモックすることは非常に困難です。

于 2012-04-17T12:00:09.547 に答える
0

個人的には、2番目の例を使用することをお勧めします。この方法では、検索ロジックを1つの場所にカプセル化し、呼び出し元の意図は、呼び出し元のメソッドの名前によって明確に定義されます。最初の例を使用すると、クエリコードがアプリケーション全体にリークし、クエリが重複することになります。

于 2012-04-17T11:35:11.390 に答える
0

実は1枚目がいいと思います。私は次の要因についての私の決定を前提としています。

  1. 製品構造がリファクタリングされる場合:

    • IQueryableアプローチ-コード内の呼び出しメソッドを変更するだけで済みます。
    • IEnumerables-メソッド名も変更する必要があります。

  2. 多くの人が多形的な方法で反復したいインターフェースを導き出そうとしている場合:

    • IQueryableアプローチ-一般的な統一メソッド名の利点
    • IEnumerables-一部の名前は、必要なメソッドを説明していない可能性があります。

  3. 弾力性

    • IQueryableアプローチ-IEnumerablesアプローチに簡単に分割できます。
    • IEnumerablesアプローチ-IQueryableアプローチに戻すのは困難です。

したがって、デフォルトの選択肢としてIQueryableから始めることをお勧めします。コードを進めていくと、必要なより具体的なIEnumerablesアプローチにいつでも変更できます。

于 2012-04-17T12:00:01.460 に答える
0

重複を避けることをお勧めします。それが最初の目標です。いくつかの場所で文字で始まる製品を見つけるロジックがある場合、それは特別なケースであり、別のメソッドに抽出する価値があります (また、特定のケースの適切な説明も提供します)。重複のないコードは、変更、理解、保守がはるかに簡単です。

IQueryableそのため、複数回使用するメソッドのセットと1 つの汎用検索メソッドを使用する傾向があります。

interface IRepository<T>
{
    IQueryable<T> FindAll();
}

interface IProductRepository : IRepository<Product>
{
    IEnumerable<Product> GetProductsInCategory(int categoryId);
    IEnumerable<Product> GetProductsStartingWith(string letter);
    IEnumerable<PromoCode> GetProductPromoCodes(int productId);
}

単体テストも検討してください。特定のメソッドは、IQueryable よりもはるかに簡単にモックできます。

于 2012-04-17T11:37:13.327 に答える