リポジトリパターンとDAL


93

それらは同じものですか?Rob ConneryのStorefrontチュートリアルの視聴を終えたばかりで、それらは同様のテクニックのようです。つまり、DALオブジェクトを実装するときは、GetStuff、Add / Deleteなどのメソッドを使用し、後でdbを切り替えられるように、常に最初にインターフェイスを記述します。

混乱しますか?

回答:


88

あなたは間違いなく物事を混乱させる人ではありません。:-)

質問への答えは、どれだけ純粋主義者になりたいかにかかっていると思います。

厳密なDDDの視点が必要な場合は、1つのパスをたどります。リポジトリを、サービスとデータベースを分離するレイヤーのインターフェースを標準化するのに役立つパターンと見なすと、別のレイヤーに移動します。

私の観点から見たリポジトリは、データへのアクセスの明確に指定されたレイヤーにすぎません。つまり、データアクセスレイヤーを実装するための標準化された方法です。リポジトリの実装にはいくつかの違いがありますが、概念は同じです。

リポジトリにさらにDDD制約を課す人もいれば、データベースとサービス層の間の便利なメディエーターとしてリポジトリを使用する人もいます。DALのようなリポジトリは、サービスレイヤーをデータアクセスの詳細から分離します。

それらを異なるように見せている実装上の問題の1つは、仕様をとるメソッドを使用してリポジトリが作成されることが多いことです。リポジトリは、その仕様を満たすデータを返します。私が見てきたほとんどの従来のDALには、メソッドが任意の数のパラメーターを取る、より大きなメソッドセットがあります。これは小さな違いのように聞こえるかもしれませんが、Linqと式の領域を入力するとき、それは大きな問題です。デフォルトのリポジトリインターフェースは次のようになります。

public interface IRepository : IDisposable
{
    T[] GetAll<T>();
    T[] GetAll<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter);
    T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
    void Delete<T>(T entity);
    void Add<T>(T entity);
    int SaveChanges();
    DbTransaction BeginTransaction();
}

これはDALまたはリポジトリですか?この場合、私はその両方を推測します。

キム


5
ここではパーティーに遅れますが、なぜList <T>(または同様の)ではなくT []なのでしょうか。
マイクキングスコット2010

27
おそらくIEnumerable <T>が最適でしょう。
Venemo 2010

9
またはIQueryable <T>
kenwarner 2010

1
IQueryable <T>が最良の選択だと思います。これにより、メソッドをチェーンして実行を延期し、データベースにすべての作業を任せることができるからです。
0lukasz0

4
@kenwarner IQueryable <T>を返すと抽象化がリークすると思います。リポジトリからドメインオブジェクトを返す必要があります。
マシュー

42

リポジトリはさまざまな方法で適用できるパターンですが、データアクセスレイヤーには非常に明確な責任があります。DALはデータストレージに接続してCRUD操作を実行する方法を知っている必要があります。

リポジトリ DALにすることもできますが、DALの前に配置して、ビジネスオブジェクトレイヤーとデータレイヤーの間のブリッジとして機能させることもできます。使用される実装はプロジェクトごとに異なります。


23

1つの大きな違いは、DAOはドメイン内のエンティティの永続性を処理する一般的な方法であることです。一方、リポジトリは集約ルートのみを扱います。


26
最初に理解することは、パターンとしてのリポジトリは、ドメイン駆動設計と呼ばれるより大きなシステムの一部であることです。DDDドメインオブジェクトは、それぞれが集合ルートを持つ集合にグループ化されます。たとえばPurchaseOrderは集約ルートであり、OrderItemsは集約ルート内の子です。リポジトリは集約ルートのみを扱います。つまり、たとえばOrderItemは、その集計ルートとは無関係にロードされることはありません。したがって、DDDにOrderItemリポジトリーが存在することはありません。ただし、DDD以外のシステムでは、Daoはルートの集計に制限されていないため、OrderItemDaoを使用できます。
圧倒的な2009

NG、ありがとう!私はそれをそのように見始めましたが、これはそれを明確にします。DDDに関するすべての資料を読み始める必要があります。
デビッド

@bingle、集約ルートの優れた説明、およびリポジトリーによる子オブジェクトのロード方法。多層アプリケーションのどこにリポジトリが存在しますか?データアクセスレイヤーライブラリにあるのがわかりましたが、子オブジェクトを読み込むので、ロジックレイヤーライブラリに存在する必要がありますか?私の直感はデータアクセスレイヤーを教えてくれますが、私はあなたの意見を望んでいました。
Jeff LaFay 2013年

12

私は同様の質問への回答を探していて、2つの最高ランクの回答に同意しました。自分のためにこれを明確にしようとすると、私が発見した場合は、リポジトリパターンと手に手を行く仕様は、ドメインモデルのファーストクラスのメンバーとして実装され、その後、私ができます

  • 異なるパラメーターで仕様定義を再利用し
  • 既存の仕様インスタンスのパラメーターを操作する(たとえば、特殊化する)
  • それらを組み合わせる
  • データベースアクセスを行うことなく、ビジネスロジック実行します。
  • そしてもちろん、実際のリポジトリ実装とは関係なく、それらを単体テストします。

私はこれまでのところ、Repositoryパターンが仕様パターンと一緒に使用されない限り、それは実際には「リポジトリ」ではなくDALであると述べているかもしれません。疑似コードの不自然な例:

specification100 = new AccountHasMoreOrdersThan(100)
specification200 = new AccountHasMoreOrdersThan(200)

assert that specification200.isSpecialCaseOf(specification100)

specificationAge = new AccountIsOlderThan('2000-01-01')

combinedSpec = new CompositeSpecification(
    SpecificationOperator.And, specification200, specificationAge)

for each account in Repository<Account>.GetAllSatisfying(combinedSpec)
    assert that account.Created < '2000-01-01'
    assert that account.Orders.Count > 200

詳細については、Fowler's Specification Essayを参照してください(これは、上記に基づいています)。

DALには、次のような特殊なメソッドがあります。

IoCManager.InstanceFor<IAccountDAO>()
    .GetAccountsWithAtLeastOrdersAndCreatedBefore(200, '2000-01-01')

特に、この方法で各DAL / DAOインターフェイスを定義し、DALクエリメソッド実装する必要があるため、これがいかに面倒になるかを理解できます。

.NETでは、LINQクエリ仕様を実装する1つの方法ですが、仕様(式)の組み合わせは、自社開発のソリューションほどスムーズではない場合があります。そのためのいくつかのアイデアは、このSO質問で説明されています。


2

私の個人的な意見では、それはすべてマッピングに関するものであると考えています。http//www.martinfowler.com/eaaCatalog/repository.htmlを参照してください。したがって、リポジトリからの出力/入力はドメインオブジェクトであり、DALでは何でもかまいません。私にとって、これは重要な追加/制限です。異なるレイアウトでデータベース/サービス/リポジトリの実装を追加でき、マッピングを行うことに集中できる明確な場所があるからです。その制限を使用せず、他の場所にマッピングがある場合は、データを表す別の方法を使用すると、変更してはならない場所のコードに影響を与える可能性があります。


1

それはすべて解釈と文脈に関するものです。それらは非常によく似ていたり、非常に異なっていたりしますが、ソリューションが機能する限り、名前には何が含まれていますか。


1

リポジトリはパターンです。これは、標準化された方法で実装してコードを再利用する方法です。


1

リポジトリパターンを使用する利点は、データアクセスレイヤーをモックすることです。これにより、DALコードを呼び出さずにビジネスレイヤーコードをテストできます。他にも大きな利点がありますが、これは私にとって非常に重要なようです。


1
DALをモックすることはできますが、それ自体がリポジトリである必要はありません。重要な点は、どのようなデータアクセス戦略を使用しても、インターフェイスを実装する必要があるということです。これにより、IoCコンテナーを使用できるだけでなく、データストアを必要とせずにビジネスコードをきちんとテストできます。
cdaq 2013

0

私が理解していることから、それらは基本的に同じことを意味する可能性がありますが、ネーミングはコンテキストに基づいて異なります。

たとえば、IRepositoryインターフェイスを実装するDal / Daoクラスがあるとします。

Dal / Daoはデータレイヤー用語です。アプリケーションの上位層はリポジトリの観点から考えています。


0

では、(単純な)ほとんどの場合、DAOはリポジトリの実装ですか?

私が理解している限り、DAOはdbアクセス(CRUD-選択なし?!)を正確に処理しているようですが、リポジトリではデータアクセス全体を抽象化できます。

私は正しい道を進んでいますか?


実際、私はそれを逆にして、単純化の観点からすると、リポジトリはDAOの特定の実装スタイルであると言いますが、そうです、あなたは正しい道を進んでいます。(CRUDからのR =読み取り、それがあなたの選択です。)
Jeromy Irvine

0

外界(つまり、クライアントコード)のリポジトリは、以下を除いてDALと同じです。

(1)挿入/更新/削除メソッドは、データコンテナーオブジェクトをパラメーターとして持つように制限されています。

(2)読み取​​り操作の場合、DAL(たとえば、GetByPK)のような単純な仕様または高度な仕様をとることがあります。

内部的には、データマッパーレイヤー(エンティティフレームワークコンテキストなど)と連携して、実際のCRUD操作を実行します。

リポジトリパターンが意味しないもの:-

また、挿入/更新/削除メソッドによって実行されるすべてのメモリ内の変更をデータベースにコミットする挿入/更新/削除メソッドの他に、リポジトリパターンのサンプル実装として、別のSaveメソッドがあると混乱することがよくあります。リポジトリにSaveメソッドを確実に含めることができますが、インメモリCUD(作成、更新、削除)と永続化メソッド(データベースで実際の書き込み/変更操作を実行)を分離することはリポジトリの責任ではありませんが、作業単位パターンの責任。

お役に立てれば!


0

「リポジトリ」は特定のクラスであり、「DAL」はリポジトリ、DTO、ユーティリティクラス、およびその他必要なもので構成される層全体であると主張することができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.