2010-01-19 2 views
5

고객 및 주문 행과 관련된 Order 유형의 집계 루트 엔티티가 있다고 가정 해 보겠습니다. 주문 실체를 생각할 때 ID 없이는 개념화하지 않는 것이 더 자연 스럽습니다. Id가없는 주문은 주문보다 주문 요청으로 더 잘 표현되는 것 같습니다.저장소에 집계 루트를 추가하는 방법은 무엇입니까?

class OrderRepository 
{ 
    void Add(Order order) 
    { 
     // Insert order into db and populate Id of new order 
    } 
} 

내가이 접근 방식에 대해 좋아하는 것은 당신이를 추가하는 것입니다 :

, 나는 보통 사람들이 아이디없이 순서를 인스턴스화 한 다음 저장소 개체를 완료해야 볼 저장소에 명령을 추가하려면 OrderRepository에 인스턴스를 주문하십시오. 그것은 많은 의미가 있습니다. 그러나 주문 인스턴스에는 ID가없고 저장소의 소비자 범위에서는 주문에 Id가 없다는 사실이 여전히 나에게 전혀 들지 않습니다. OrderRequest를 순서의 인스턴스로 정의하고 저장소에 추가 할 수는 있지만 오렌지에서 사과를 파생시킨 다음 오렌지 목록에 추가하는 것과 같습니다.

class OrderRepository 
{ 
    Order AddOrder(Customer customer) 
     // It might be better to call this CreateOrder 
    { 
     // Insert record into db and return a new instance of Order 
    } 
} 

내가이 접근 방식에 대해 좋아하는 것은 순서가 이드가없이 정의되지 않은 점이다 :

또한, 나는 또한이 방법을 보았다. 리포지토리는 주문 인스턴스를 만들고 반환하기 전에 데이터베이스 레코드를 만들고 모든 필수 필드를 수집 할 수 있습니다. 여기서 냄새가 난다는 사실은 저장소의 주문 인스턴스를 실제로 저장소에 추가하지 않는다는 사실입니다.

어느 쪽이든 작동하므로 제 질문은 다음과 같습니다.이 두 가지 해석 중 하나와 함께 살아야합니까? 아니면 삽입을 모델링하는 것이 가장 좋습니다.

이 답변은 비슷하지만 값 개체의 경우 : how should i add an object into a collection maintained by aggregate root입니다. 가치 객체에 관해서 혼란은 없지만 내 질문은 외부 소스 (Auto-Generated Database Id)에서 파생 된 ID를 가진 객체와 관련이 있습니다.

+0

나는 이드가없는 Order가 Order Entity가 아니라고 주장한다. 이 문제를 해결하려면 개체의 상태를 기억해야합니다. '상태'를 시간의 멈춤으로보십시오. 즉, 웹 페이지 요청. 순서를 생성하는 동안 예, 처음에는 ID가 없지만 상태는 아직 완료되지 않았습니다. 저장소에 추가()하여 Order()의 지속 상태를 완료합니다. 완전한. – eduncan911

+0

나는 아직 당신과 동의하지 않는다. 그러나 당신이없이 주문을하고 Id가 잠시 동안 잠깐 동안 엔티티라고 주장하면, 그 일시 중지 동안에는 식별 할 수있는 신원이 없을 것이다. 적어도 의미 론적으로 이것이 엔티티의 정의와 모순이라고 생각합니다. –

+0

정체성은 당신이 생각하는 것처럼 잘리고 건조하지 않습니다. 제 믿음으로, 우리의 정체성은 우리의 개념에서 나온 우리의 독특한 영혼입니다. 그러나 정부에 대해 우리의 정체성은 출생 증명서, 여권 등 여러 가지 방법을 통해 확립 될 수 있습니다. 아이에게 정부에 대한 공식적인 정체성이없는 시점이 있지만 정부는 신원을 필요로하지만 기업을 여전히 실체로 간주합니다. 귀중한 작은 아기 및 정부 (ints가 더 사용자 친화적 인 어쨌든입니다!)로 저장소로 생각하십시오 :) – tuespetre

답변

5

두 번째 방법을 배제하고 싶습니다. 반 직관적 일뿐만 아니라 Command-Query SeparationPrinciple of Least Surprise과 같은 여러 좋은 디자인 원칙을 위반합니다.

나머지 옵션은 도메인 논리에 따라 다릅니다. 도메인 로직은 ID가없는 주문이 의미가 있음을 지시하는 경우, ID 주문의 필수 불변이며, 우리는 그래서 모델해야합니다 readonlyid 필드를 표시하여 우리가 만든 것을

public class Order 
{ 
    private readonly int id; 

    public Order(int id) 
    { 
     // consider a Guard Clause here if you have constraints on the ID 
     this.id = id; 
    } 
} 

공지 사항 불변성. 주어진 Order 인스턴스에 대해이를 변경할 수있는 방법은 없습니다. 이것은 Domain-Driven Design엔티티 패턴과 완벽하게 맞습니다.

ID가 음수 또는 0이되지 않도록 Guard 절을 생성자에 추가하여 도메인 논리를 강화할 수 있습니다.

이제는 데이터베이스의 자동 생성 ID로 어떻게 작동하는지 궁금 할 것입니다. 음, 그렇지 않습니다.

제공된 ID가 이미 사용되고 있지 않은지 확인하는 좋은 방법은 없습니다.

  • 변경 GUID가에 대한 ID :이 옵션을 잎

    . 이렇게하면 모든 발신자가 새 주문에 대한 고유 ID를 제공 할 수 있습니다. 그러나이를 위해서는 Guids를 데이터베이스 키로 사용해야합니다.

  • 새 주문을 만들 때 Order 개체가 아니라 OrderRequest를 사용하도록 API를 변경하십시오. OrderRequest는 Order 클래스와 거의 동일 할 수 있으며 ID를 뺀 값이 될 수 있습니다.

많은 경우에 새로운 주문을 만드는 것은 어떤 경우에도 특정 모델링이 필요한 비즈니스 운영이므로이 구분을 만드는 데 아무런 문제가 없습니다. Order와 OrderRequest는 의미 상 매우 유사 할지라도 형식 계층 구조와 관련 될 필요조차 없습니다.

OrderRequest 주문 반면 값 개체이기 때문에 더욱, 지금까지 그들이 이 관련되어서는 안된다는 말을하기로 갈 수도는 엔티티입니다.

이 방법을 사용하면 AddOrder 메서드는 방금 만든 Order의 ID를 알 수 없기 때문에 Order 인스턴스 (또는 적어도 ID)를 반환해야합니다. 이로 인해 CQS 위반으로 이어집니다. 따라서 은 GUID (엔터티 ID)를 선호하는 경향이 있습니다.

+0

좋은 답변! 전에 질문을하기 전에 OrderRequest를 수락하기 위해 API를 변경하는쪽으로 기울어 져 있었으며 Order 계층에 포함되지 않은 값 객체 여야한다는 데 동의합니다. 그러나 이제는 내가 Guid 제안을 정말 좋아합니다. 고유 한 것으로 인스턴스화하는 방법을 알고있는 Order 생성자를 정의한 다음 저장소에 추가 할 수 있습니다. 나에게 완벽하게 들린다. 그러나이 솔루션은 일반적인 관행을 벗어나는 것처럼 보이기 때문에 불안합니다. 이 솔루션을 사용하고 싶지만 허락되지 않은 프로젝트가 많이 있었습니까? –

+0

몇 가지 이유로이 방법이 좋지 않다고 생각하는 사람들이 발생할 수 있습니다. 그 중 일부는 주로 응용 프로그램 아키텍처에 대한 Cargo Cult 접근 방식과 관련이 있지만 저항은 여전히 ​​실제 일 수 있습니다. 일반적으로 int 대신 keys로 Guids를 사용하는 데 작은 오버 헤드 오버 헤드가 있지만 지금까지 나를 멈추게 한 것은 없습니다. Guids에 대한 가장 중요한 논쟁은 응용 프로그램 외부에서 ID를 사용하는 경우입니다. ID가 전화기를 통해 소리내어 읽기가 어렵 기 때문입니다 (예를 들어). Guids를 사용하면 일부 문제는 해결되지만 전부는 아닙니다. 나는 Guids를 선호하지만, 다른 대안들에 대해서도 개방되어 있습니다 :) –

+0

Order와 OrderRequest가 분리되어 있다면 그것은 유지 보수 지옥이 될 것입니다, 그렇지 않습니까?ID 필드를 제외하고는 서로를 완전히 반영하기 때문에 항상 진화해야합니다. 또는 나는 무엇인가 놓치고 있냐? – vorou

관련 문제