문제

나는 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) 쿼리를 작성하는 데 어려움을 겪고 더 많은 작업이 어려워 보이지만 사양 레이어로의 교차 오염을 제한합니다.

4) 내가 가장 좋아하지 않지만 가장 직접적인 구현과 아마도 대부분의 데이터베이스는 복잡한 쿼리에 효율적이지만 호출 코드에 많은 책임이 있습니다.

도움이 되었습니까?

해결책

나는 그들이 모두 좋은 옵션이라고 생각합니다 (아마도 당신이 nhibernate에 묶고 싶지 않은 경우 4를 제외하고), 현재의 노력에 따라 스스로 결정을 내릴 수있는 장단점을 잘 분석 한 것 같습니다. 자신을 이기지 마십시오 ~도 이것에 열심히.

나는 현재 2와 3 사이의 혼합물을 연구하고 있습니다.

public interface IRepository<T> 
{
        ...
        IList<T> FindAll();
        IList<T> FindBySpec(ISpecification<T> specification);
        T GetById(int id);
}

public interface ISpecificRepository : IRepository<Specific> 
{
        ...
        IList<Specific> FindBySku(string sku);
        IList<Specific> FindByName(string name);
        IList<Specific> FindByPrice(decimal price);
}

그리고 기본 클래스의 저장소도 있습니다.

다른 팁

"위의 어느 것도"접근법에 대한 좋은 주장도 있습니다.

일반 리포지토리의 문제점은 시스템의 모든 객체가 4 가지 CRUD 작업 (생성, 읽기, 업데이트, 삭제)을 모두 지원한다는 가정을한다는 것입니다. 그러나 복잡한 시스템에는 몇 가지 작업 만 지원하는 객체가있을 수 있습니다. 예를 들어, 읽기 전용 객체 또는 생성되었지만 업데이트되지 않은 객체가있을 수 있습니다.

Irepository 인터페이스를 읽기, 삭제 등으로 작은 인터페이스로 나눌 수 있지만 매우 빨리 지저분 해집니다.

Gregory Young은 (DDD / 소프트웨어 레이어링 관점에서) 각 저장소가 작업중인 도메인 개체 또는 집계에 특정한 작업 만 지원해야한다는 좋은 주장을합니다. 그의 기사는 다음과 같습니다 일반 리포지토리.

그리고 다른 시야를 보려면이 Ayende를 참조하십시오 블로그 게시물.

우리가하고있는 일 중 하나는 모든 리포지토리가 다른 요구를 가지고있어 인터페이스 모음을 만들고 있다는 것입니다.

public interface IReadOnlyRepository<T,V>
{
   V Find(T);
}

이 예에서는 읽기 전용 저장소가 데이터베이스에서 가져옵니다. t, v의 이유는 v가 저장소에 의해 반환되는 것을 나타내고 t는 통과 된 것을 나타내므로 다음과 같이 할 수 있습니다.

public class CustomerRepository:IReadOnlyRepository<int, Customer>, IReadOnlyRepository<string, Customer>
{
    public Customer Find(int customerId)
    {
    }

    public Customer Find(string customerName)
    {
    }
}

ADD, 업데이트 및 삭제에 대한 별도의 인터페이스를 만들 수도 있습니다. 이렇게하면 내 저장소에 동작이 필요하지 않으면 인터페이스를 구현하지 않습니다.

나는 찾기 방법에 대한 iqueryable <> 반환 값에 적용 할 수있는 것보다 필터와 페이징 확장 방법을 만들 수 있기 때문에 1의 BIF 팬입니다. 확장 방법을 데이터 계층에 보관 한 다음 비즈니스 계층에서 즉시 구성합니다. (완전히 순수하지 않습니다.)

물론 시스템이 안정화되면 동일한 확장 방법을 사용하여 특정 찾기 메소드를 만들고 func <>을 사용하여 최적화 할 수있는 옵션이 있습니다.

LINQ와 함께 NH를 사용하는 경우 리포지토리는 다음과 같습니다.

session.Linq<Entity>()

사양은 다음을 다루는 것입니다.

IQueryable<Entity>

당신이 원한다면 그것을 모두 외면 할 수 있지만, 그것은 추상화를 추상화하기위한 많은 일상적인 작업입니다.

단순한 것이 좋습니다. Yah, NH는 데이터베이스를 수행하지만 더 많은 패턴을 제공합니다. 달 이외의 사람들이 NH에 의존하는 것은 죄와는 거리가 멀다.

나는 그것이 당신의 필요에 달려 있다고 생각합니다. 사용하려는 다른 설계 패턴과 함께 저장소에 대해 생각하는 것이 중요합니다. 마지막으로, 그것은 저장소에서 무엇을 기대하는지에 달려 있습니다 (사용의 주요 이유는 무엇입니까).

엄격한 계층을 만들어야합니까 (예 : NHibernate를 향후 엔티티 프레임 워크로 교체해야합니까)? 특히 저장소 방법에 테스트를 작성 하시겠습니까?

저장소를 만드는 가장 좋은 방법은 없습니다. 몇 가지 방법이 있으며 확실히 당신에게 달려 있습니다. 당신의 요구에 가장 실용적인 것은 무엇입니까?

저장소와 함께

Lostechies의 Jimmy Bogard의 관련 기사

http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/09/10/wither-the-repository.aspx

또한 버전 #2를 제안하는 일부 의견이있는 또 다른 빠른 기사는 실제로 DOA 패턴이며 저장소가 아닙니다.

http://fabiomaulo.blogspot.com/2009/06/linq-and-repository.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top