리포지토리 패턴 대 DAL


93

그들은 같은 것입니까? Rob Connery의 Storefront 튜토리얼 시청을 마쳤으며 유사한 기술인 것 같습니다. 즉, DAL 개체를 구현할 때 GetStuff, Add / Delete 등 메서드가 있고 나중에 db를 전환 할 수 있도록 항상 인터페이스를 먼저 작성합니다.

내가 헷갈 리나요?

답변:


88

당신은 확실히 일을 혼동하는 사람이 아닙니다. :-)

나는 질문에 대한 답은 당신이 얼마나 순수 주의자가되고 싶은지에 달려 있다고 생각합니다.

엄격한 DDD 관점을 원한다면 한 길을 내려갈 것입니다. 리포지토리를 서비스와 데이터베이스를 분리하는 계층의 인터페이스를 표준화하는 데 도움이 된 패턴으로 보면 다른 작업을 중단하게됩니다.

제 관점에서 저장소는 데이터에 대한 액세스의 명확하게 지정된 계층 일뿐입니다. 즉, 데이터 액세스 계층을 구현하는 표준화 된 방법입니다. 저장소 구현에 따라 약간의 차이가 있지만 개념은 동일합니다.

어떤 사람들은 저장소에 더 많은 DDD 제약을 두는 반면 다른 사람들은 데이터베이스와 서비스 계층 사이의 편리한 중재자로서 저장소를 사용할 것입니다. DAL과 같은 리포지토리는 데이터 액세스 세부 사항에서 서비스 계층을 분리합니다.

그것들을 다르게 만드는 것으로 보이는 구현 문제 중 하나는 저장소가 종종 사양을 취하는 메소드로 생성된다는 것입니다. 저장소는 해당 사양을 충족하는 데이터를 반환합니다. 내가 본 대부분의 기존 DAL에는 메서드가 여러 매개 변수를 사용하는 더 큰 메서드 집합이 있습니다. 이것은 작은 차이처럼 들릴지 모르지만 Linq와 Expressions의 영역에 들어가면 큰 문제입니다. 기본 저장소 인터페이스는 다음과 같습니다.

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
여기 파티에 늦었지만 왜 T [], List <T> (또는 유사)가 아닌가?
Mike Kingscott

27
아마도 IEnumerable <T>가 최고 일 것입니다.
Venemo

9
또는 IQueryable <T>
kenwarner

1
IQueryable <T>가 최선의 선택이라고 생각합니다. 데이터베이스가 모든 작업을 수행 할 수 있도록 메서드를 연결하고 실행을 연기 할 수 있기 때문입니다.
0lukasz0

4
@kenwarner IQueryable <T>를 반환하면 추상화가 누출된다고 생각합니다. 저장소에서 도메인 개체를 반환해야합니다.
마태 복음

42

리포지토리는 다양한 방식으로 적용 할 수있는 패턴이지만 데이터 액세스 계층에는 매우 명확한 책임이 있습니다. DAL은 CRUD 작업을 수행하기 위해 데이터 저장소에 연결하는 방법을 알아야합니다.

리포지토리 DAL 있지만 DAL 앞에 배치되어 비즈니스 개체 계층과 데이터 계층 사이의 다리 역할을 할 수도 있습니다. 어떤 구현이 사용되는지는 프로젝트마다 다릅니다.


23

한 가지 큰 차이점은 DAO는 도메인의 모든 엔티티에 대한 지속성을 처리하는 일반적인 방법이라는 것입니다. 반면에 저장소는 집계 루트 만 처리합니다.


26
가장 먼저 이해해야 할 것은 패턴으로서의 리포지토리가 도메인 기반 설계로 알려진 더 큰 시스템의 일부라는 것입니다. DDD 도메인에서 개체는 각각 집계 루트가있는 집계로 그룹화됩니다. 예를 들어 PurchaseOrder는 집계 루트이고 OrderItem은 집계 루트 내의 하위입니다. 저장소는 집계 루트 만 처리합니다. 즉, 예를 들어 OrderItem은 집계 루트와 독립적으로로드되지 않습니다. 따라서 DDD에 OrderItem 저장소가 없을 것입니다. 그러나 비 DDD 시스템에서는 Dao가 집계 루트로 제한되지 않기 때문에 OrderItemDao를 가질 수 있습니다.
dec

NG, 감사합니다! 나는 그런 식으로보기 시작했지만, 이것은 분명합니다. 나는 모든 DDD 문헌을 읽기 시작해야 할 것입니다!
David

@bingle, 집계 루트 및 저장소에서 자식 개체를로드하는 방법에 대한 훌륭한 설명. 다중 계층 애플리케이션에서 저장소는 어디에 있습니까? 데이터 액세스 계층 라이브러리에있는 것을 볼 수 있지만 자식 개체를로드하기 때문에 대신 논리 계층 라이브러리에 있어야합니까? 내 직감은 데이터 액세스 레이어를 말하지만 문제에 대한 귀하의 의견을 원했습니다.
Jeff LaFay 2013-06-05

12

나는 비슷한 질문에 대한 답을 찾고 있었고 가장 높은 두 개의 답변에 동의합니다. 이것을 명확히하기 위해 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의 사양 에세이 를 참조하십시오 (위의 내용을 기반으로 한 것입니다).

DAL에는 다음과 같은 특수한 방법이 있습니다.

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

당신은 당신이이 방법으로 DAL / DAO 인터페이스의 각을 정의해야 특히 이후,이 신속 성가신 될 수있는 방법을 볼 수 있습니다 DAL 쿼리 방법을 구현한다.

.NET에서 LINQ 쿼리 사양을 구현하는 한 가지 방법이 될 있지만 사양 (표현식)을 결합하는 것은 자체 개발 한 솔루션만큼 원활하지 않을 수 있습니다. 이에 대한 몇 가지 아이디어는 이 SO 질문에 설명되어 있습니다.


2

내 개인적인 의견은 매핑에 관한 것입니다. http://www.martinfowler.com/eaaCatalog/repository.html을 참조 하십시오 . 따라서 리포지토리의 출력 / 입력은 DAL에서 무엇이든 될 수있는 도메인 개체입니다. 저에게는 중요한 추가 / 제한 사항입니다. 다른 레이아웃으로 데이터베이스 / 서비스에 대한 리포지토리 구현을 추가 할 수 있고 매핑에 집중할 수있는 명확한 위치가 있기 때문입니다. 이 제한을 사용하지 않고 다른 곳에 매핑을하는 경우 데이터를 표현하는 다른 방법을 사용하면 변경해서는 안되는 위치의 코드에 영향을 미칠 수 있습니다.


1

해석과 맥락에 관한 것입니다. 그들은 매우 유사하거나 실제로 매우 다를 수 있지만 솔루션이 작동하는 한 이름은 무엇입니까!


1

리포지토리는 패턴이며, 가능한 한 코드를 재사용 할 수 있도록 표준화 된 방식으로 구현하는 방법입니다.


1

리포지토리 패턴 사용의 장점은 DAL 코드를 호출하지 않고도 비즈니스 계층 코드를 테스트 할 수 있도록 데이터 액세스 계층을 모의하는 것입니다. 다른 큰 장점이 있지만 이것은 나에게 매우 중요한 것 같습니다.


1
여전히 DAL을 모의 처리 할 수 ​​있으며 저장소 자체가 될 필요는 없습니다. 중요한 점은 어떤 데이터 액세스 전략을 사용하든 인터페이스를 구현해야한다는 것입니다. 이를 통해 IoC 컨테이너를 사용할 수있을뿐만 아니라 데이터 저장소 없이도 비즈니스 코드를 깔끔하게 테스트 할 수 있습니다.
cdaq

0

내가 이해하는 바에 따르면 기본적으로 동일한 의미를 가질 수 있지만 이름은 컨텍스트에 따라 다릅니다.

예를 들어 IRepository 인터페이스를 구현하는 Dal / Dao 클래스가있을 수 있습니다.

Dal / Dao는 데이터 레이어 용어입니다. 애플리케이션의 상위 계층은 리포지토리 측면에서 생각합니다.


0

그래서 대부분의 (간단한) 경우 DAO는 Repository의 구현입니까?

내가 이해하는 한, DAO는 db 액세스 (CRUD-No selects ?!)를 정확하게 처리하는 반면 Repository를 사용하면 전체 데이터 액세스를 추상화 할 수 있습니다.

나는 올바른 길을 가고 있는가?


사실, 나는 그것을 뒤집고 단순한 관점에서 Repository는 DAO에 대한 특정 구현 스타일이라고 말하고 싶습니다.하지만 그렇습니다. (CRUD의 R = 읽기이므로 선택합니다.)
Jeromy Irvine

0

외부 세계 (예 : 클라이언트 코드)에서 저장소는 다음을 제외하고 DAL과 동일합니다.

(1) 삽입 / 업데이트 / 삭제 방법은 데이터 컨테이너 개체를 매개 변수로 사용하도록 제한됩니다.

(2) 읽기 작업의 경우 DAL (예 : GetByPK) 또는 고급 사양과 같은 간단한 사양이 필요할 수 있습니다.

내부적으로 데이터 매퍼 레이어 (예 : 엔터티 프레임 워크 컨텍스트 등)와 함께 작동하여 실제 CRUD 작업을 수행합니다.

리포지토리 패턴이 의미하지 않는 것 :-

또한 삽입 / 업데이트 / 삭제 메서드가 수행 한 모든 메모리 내 변경 사항을 데이터베이스에 커밋하는 Insert / Update / Delete 메서드 외에 리포지토리 패턴 샘플 구현으로 별도의 Save 메서드를 사용하는 것에 대해 사람들이 종종 혼동하는 것을 보았습니다. 우리는 저장소에 저장 방법을 확실히 가질 수 있지만 메모리 내 CUD (생성, 업데이트, 삭제) 및 지속성 방법 (데이터베이스에서 실제 쓰기 / 변경 작업을 수행)을 격리하는 저장소의 책임은 아니지만 작업 단위 패턴의 책임.

도움이 되었기를 바랍니다!


0

"리포지토리"는 특정 클래스이고 "DAL"은 리포지토리, DTO, 유틸리티 클래스 및 기타 필요한 항목으로 구성된 전체 계층이라고 주장 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.