Я изучал BDD / DDD и, как следствие, пытался придумать правильную реализацию шаблона Repository. До сих пор было трудно найти консенсус в отношении наилучшего способа реализации этого. Я пытался свести его к следующим вариантам, но я не уверен, что это лучший подход.
Для справки я создаю приложение ASP.MVC с NHibernate в качестве бэк-энда.
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) Моя наименее любимая, но, возможно, самая прямая реализация и, возможно, наиболее эффективная база данных для сложных запросов, хотя это накладывает большую ответственность на вызывающий код.