直接的なメリットは、特定のテクノロジーへのロックインを防ぎ、後で適切なテクノロジーを柔軟に選択できるようにすることです。
私見、もっと重要な理由は、ユビキタス言語を強制することです。アプリケーション/システムが進化するにつれて、複数の方法でデータをクエリする必要があります。リポジトリは、複雑なクエリをカプセル化するのに役立ちます。
一般的な実装では、コンシューマーコードは次のようになります。
customerRepo = ServiceLocator.Current.Resolve<IRepository<Customer>>();
var matchingCustomers = customerRepo.GetAll().Where(c => <some complex condition here>);
リポジトリを使用すると、次のようになります。
customerRepo = ServiceLocator.Current.Resolve<ICustomerRepository>();
var matchingCustomers = myRepo.GetCustomersWithOrdersPendingFor(new DateTime(2010, 12, 31));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2番目の例では、クエリの意図を明確に示しており、将来の識別が容易/迅速になります。
ただし(問題を複雑にするために)、クエリ仕様を使用して複雑なクエリロジックを分離し、汎用リポジトリで使用して作業を完了することができます。それがどのように行われるかを確認するには、この投稿を参照してください。
私は通常次のことをします:
- 汎用リポジトリーを作成します(つまり、IRepository <TAggregateRoot>)
- IRepository <TAggregateRoot>を実装して、集約ルートごとにリポジトリを作成します
- 必要に応じて、適切なリポジトリにクエリメソッドを追加します
- リポジトリが肥大化しすぎた場合は、クエリを個別のクエリ仕様にリファクタリングします
最後の注意:私はかつて、オンラインモードとオフラインモードの両方で動作するアプリを設計しました。最も簡単な解決策は、2つの具体的なリポジトリを(共通のインターフェイスを使用して)実装し、クライアントが接続/切断されたときにそれらを切り替えることでした(永続化テクノロジを切り替える別の例)。