2008-09-16 3 views
10

Evan과 Nilsson의 저서를 읽은 후에도 도메인 기반 프로젝트에서 데이터 액세스를 관리하는 방법을 아직 잘 모릅니다. CRUD 메소드가 리포지토리의 일부 (예 : OrderRepository.GetOrdersByCustomer (customer))이거나 해당 엔티티 (Customer.GetOrders())의 일부 여야합니다. 후자의 접근 방식은 더 많은 것 같지만, Customer.GetOrders(), Invoice.GetOrders(), ShipmentBatch.GetOrders() 등의 여러 객체 사이에 단일 엔터티 유형에 대한 데이터 액세스를 배포합니다. 삽입 및 업데이트는 어떻게됩니까?데이터 액세스?

답변

15

CRUD-ish 메소드는 저장소 ... ish의 일부 여야합니다. 하지만 왜 CRUD 방법이 많은지 물어봐야 할 것 같습니다. 그들은 무엇을 정말합니까? 그들은 무엇입니까 정말에 대한? 실제로 응용 프로그램에서 사용하는 데이터 액세스 패턴을 호출하면 저장소가 훨씬 유용 해지고 특정 유형의 변경이 도메인에서 발생할 때 샷건 수술을하지 않아도된다고 생각합니다.

CustomerRepo.GetThoseWhoHaventPaidTheirBill() 

// or 

GetCustomer(new HaventPaidBillSpecification()) 

// is better than 

foreach (var customer in GetCustomer()) { 
    /* logic leaking all over the floor */ 
} 

"저장"유형 메소드도 저장소의 일부 여야합니다.

집계 루트가있는 경우 리포지토리 폭발이 발생하지 않거나 논리가 확산되는 것을 방지 할 수 있습니다. 4 x 개체 엔티티 데이터 액세스 패턴이 없으며 실제로 집계에 사용하는 데이터 액세스 패턴 뿌리.

그건 내 .02 달러입니다.

2

DDD에서도 데이터 액세스 클래스와 루틴을 엔티티와 별도로 유지합니다.

이유는, 당신이 엔티티를 추가

  1. 테스트 용이성은 장기적으로
  2. 더 많은 유지 보수 문제의
  3. 분리 및 모듈 형 디자인을 향상입니다

내가 전문가는 생각하지 루틴 , 내 의견.

1

Nilsson의 DDD & P를 적용하는 성가신 일은 항상 "나는 실제 응용 프로그램에서 그렇게하지 않을 것이지만 ..."라고 시작하는 것입니다. 주제로 돌아 가기 : OrderRepository.GetOrdersByCustomer (customer)는 갈 길이 멀지 만 DDD에 관한 ALT.Net 메일 링리스트 (http://tech.groups.yahoo.com/group/altdotnet/)에 대한 토론도 있습니다.

3

나는 당신이 말한 두 가지 방식으로 모두 해왔습니다. 나의 선호하는 접근 방식은 도메인 클래스에 대해서만 걱정되는 영구 무식한 (또는 PONO - Plain Ole '.Net Object) 메소드입니다. 그들은 그들이 어떻게 지속되는지 또는 그들이 지속 되어도 아무 것도 모릅니다. 당연히 이것에 대해서는 실용적이어야하고 이드와 같은 것들을 허용해야합니다 (그렇다고하더라도 이드가있는 레이어 수퍼 유형을 사용하므로 디폴트 값 라이브와 같은 단일 지점을 가질 수 있습니다)

이 주된 이유는 단일 책임 원칙을 준수하기 위해 노력하고 있기 때문입니다. 이 원칙을 따르면 나는 코드를 훨씬 더 테스트하고 유지 보수 할 수 있다는 것을 알게되었다. 한 가지만 생각하면되므로 필요할 때 변경하는 것이 훨씬 쉽습니다.

지켜야 할 한 가지 방법은 저장소가 겪을 수있는 방법의 팽창입니다. GetOrderbyCustomer .. GetAllOrders .. GetOrders30DaysOld .. etc 등이 문제에 대한 좋은 해결책 중 하나는 Query Object 패턴을 보는 것입니다. 그런 다음 리포지토리는 쿼리 개체를 가져 와서 실행할 수 있습니다.

또한 NHibernate와 같은 것을 살펴 보는 것이 좋습니다.

5

DDD는 일반적으로 Customer.Save에서 힌트를 얻은 활성 레코드 패턴보다 저장소 패턴을 선호합니다 (예 : Identity Map, Cache, Query objects).

액티브 레코드 모델의 한 가지 단점은 거의 모든 언어에서 특정 침입 코드를 제외하고 단일 지속성 모델을 거의 가정한다는 것입니다.

저장소 인터페이스는 도메인 계층에 정의되어 있지만 데이터가 데이터베이스에 저장되어 있는지 여부는 알 수 없습니다. 리포지토리 패턴을 사용하여 InMemoryRepository를 만들면 도메인 논리를 격리하여 테스트하고 응용 프로그램의 종속성 주입을 사용하여 서비스 계층에서 SqlRepository를 인스턴스화 할 수 있습니다.

많은 사람들에게 테스트를위한 특별 저장소가 있으면 구피처럼 들리지만 저장소 모델을 사용하면 특정 응용 프로그램에 데이터베이스가 실제로 필요하지 않을 수 있습니다. 때때로 간단한 FileRepository가 트릭을 수행합니다. 자신이 필요하다는 것을 알기도 전에 데이터베이스에 자신을 웨딩하는 것이 잠재적으로 제한적입니다. 데이터베이스가 필요한 경우에도 InMemoryRepository에 대해 테스트를 실행하는 것이 훨씬 빠릅니다.

도메인 논리가 그다지 중요하지 않은 경우 DDD가 필요하지 않을 것입니다. ActiveRecord는 많은 문제에 매우 적합합니다. 특히 데이터가 대부분이고 논리가 조금이라면 특히 그렇습니다.

4

잠시 뒤로 물러서십시오. Evans는 리포지토리가 엔티티뿐만 아니라 집계 루트를 반환 할 것을 권장합니다. 따라서 고객이 주문을 포함하는 집계 루트라고 가정하면 저장소에서 고객을 가져올 때 주문이 함께 제공됩니다. Customer에서 Orders로 관계를 탐색하여 주문에 액세스합니다.

customer.Orders; 

질문에 대답하기 위해 CRUD 작업은 집계 루트 리포지토리에 있습니다.

CustomerRepository.Add(customer); 
CustomerRepository.Get(customerID); 
CustomerRepository.Save(customer); 
CustomerRepository.Delete(customer);