私は BDD/DDD を調査しており、その結果、リポジトリ パターンの適切な実装を考え出そうとしています。これまでのところ、これを実装する最善の方法についてコンセンサスを見つけるのは困難でした。次のバリエーションに煮詰めようとしましたが、どれが最善のアプローチかはわかりません。
参考までに、バックエンドとしてNHibernateを使用してASP.MVCアプリケーションを構築しています。
public interface IRepository<T> {
// 1) Thin facade over LINQ
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Remove(T entity);
IQueryable<T> Find();
// or possibly even
T Get(Expression<Func<T, bool>> query);
List<T> Find(Expression<Func<T, bool>> query);
}
public interface IRepository<T> {
// 2) Custom methods for each query
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Remove(T entity);
IList<T> FindAll();
IList<T> FindBySku(string sku);
IList<T> FindByName(string name);
IList<T> FindByPrice(decimal price);
// ... and so on
}
public interface IRepository<T> {
// 3) Wrap NHibernate Criteria in Spec pattern
void Add(T entity);
void Update(T entity);
void Remove(T entity);
IList<T> FindAll();
IList<T> FindBySpec(ISpecification<T> specification);
T GetById(int id);
}
public interface IRepository<T> {
// 4) Expose NHibernate Criteria directly
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Remove(T entity);
IList<T> FindAll();
IList<T> Find(ICriteria criteria);
// .. or possibly
IList<T> Find(HQL stuff);
}
私の最初の考えは、
1) 効率の観点からは優れていますが、複雑になると問題が発生する可能性があります。
2) 非常に退屈なようで、非常に混雑したクラスになる可能性があります。
3) 前もってクエリを作成するのは難しく、より多くの作業が必要に思えますが、相互汚染は Specs レイヤーだけに限定されます。
4) あまり好きではありませんが、おそらく最も直接的な実装であり、複雑なクエリに対して最も効率的なデータベースですが、呼び出し元のコードに多くの責任が課せられます。