2010-05-25 2 views
5

저는 응용 프로그램/도메인 계층에서 DDD를 사용하여 event-sourced CQRS 구현 작업을하고 있습니다. 지금까지, 사람과 예약이 모두 두 가지 이유에 대한 별도의 집계 뿌리입니다이벤트 출처가있는 집계 루트가 이벤트 소싱 저장소에 액세스 할 수 있습니까?

DDD에 대한 이해와
public class Person : AggregateRootBase 
{ 
    private Guid? _bookingId; 

    public Person(Identification identification) 
    { 
     Apply(new PersonCreatedEvent(identification)); 
    } 

    public Booking CreateBooking() { 
     // Enforce Person invariants 
     var booking = new Booking(); 
     Apply(new PersonBookedEvent(booking.Id)); 
     return booking; 
    } 

    public void Release() { 
     // Enforce Person invariants 
     // Should we load the booking here from the aggregate repository? 
     // We need to ensure that booking is released as well. 
     var booking = BookingRepository.Load(_bookingId); 
     booking.Release(); 
     Apply(new PersonReleasedEvent(_bookingId)); 
    } 

    [EventHandler] 
    public void Handle(PersonBookedEvent @event) { _bookingId = @event.BookingId; } 

    [EventHandler] 
    public void Handle(PersonReleasedEvent @event) { _bookingId = null; } 
} 

public class Booking : AggregateRootBase 
{ 
    private DateTime _bookingDate; 
    private DateTime? _releaseDate; 

    public Booking() 
    { 
     //Enforce invariants 
     Apply(new BookingCreatedEvent()); 
    } 

    public void Release() 
    { 
     //Enforce invariants 
     Apply(new BookingReleasedEvent()); 
    } 

    [EventHandler] 
    public void Handle(BookingCreatedEvent @event) { _bookingDate = SystemTime.Now(); } 
    [EventHandler] 
    public void Handle(BookingReleasedEvent @event) { _releaseDate = SystemTime.Now(); } 
    // Some other business activities unrelated to a person 
} 

: :이처럼 보이는 개체 모델이

  1. 가 있습니다 시간을 때 비즈니스 구성 요소 것 데이터베이스와 별도로 Booking 개체를 끌어옵니다. (즉, 발표 된 사람이 잘못된 정보로 인해 이전 예약이 수정 된 경우).
  2. 예약을 업데이트해야 할 때마다 Person과 Booking간에 잠금 경합이 없어야합니다.

기타 비즈니스 요구 사항 중 하나는 한 번에 한 명 이상 사람을 위해 예약 할 수 없다는 것입니다. 이 때문에 잠재적으로 일부 불일치가있을 수 있으므로 (CQRS를 사용하고 결국 일관성있는 읽기 데이터베이스가 있기 때문에) 읽기 측에서 쿼리 데이터베이스를 쿼리하는 데 걱정이됩니다.

개체의 ID로 이벤트 소스 저장소를 쿼리 할 수 ​​있어야합니까 (필요한 경우 지연로드)? 더 이해하기 쉬운 구현 방법이 있습니까?

+0

"(식별 식별) { 적용 (새 PersonCreatedEvent (식별)); } 공공 사람"당신이 메모리에서 개체를 구축하는 경우 어떤 일이 발생, 당신은 새로운 사람을 만들지 않았하지만 당신은 출판 될 것입니다 새로운 사건. 나는 이벤트 핸들러를 정의하는 방식을 좋아한다.그래서 객체의 상태가 리포지토리에 명령을 적용 할 때만 변경 될 수 있다는 것을 알고 있으므로 전체 이벤트 기반으로 진행하지 않는 한 명령 핸들러도 추가해야합니다. IMHO는별로 의미가 없습니다. – Marco

+0

내가 알 수없는 것은 자신의 저장소가 게시해야하는 이벤트를 처리하는 이유입니다. "BookingCreatedEvent" – Marco

답변

10

우선, 정말로 필요한 경우 이벤트 소싱이 필요합니까? 그것은 나에게 꽤 간단 해 보인다. 이벤트 소싱에는 장점과 단점이 있습니다. 무료 감사 기록을 제공하고 도메인 모델을 표현력있게 표현하지만 솔루션을 복잡하게 만듭니다.

좋아요,이 시점에서 귀하는 귀하의 결정을 검토 한 것으로 간주하고 귀하는 이벤트 소싱에 동의 할 것으로 판단됩니다. 나는 당신이 메시징의 개념을 집계 간의 의사 소통 수단으로 놓치고 있다고 생각한다. 이것은 Pat Helland's paper에서 가장 잘 설명됩니다 (이는 BTW, DDD 또는 Event Sourcing이 아니라 확장성에 관한 것입니다).

집계는 일부 동작을 강제하기 위해 메시지를 서로 보낼 수 있다는 아이디어입니다. 일관성 문제가 발생하기 때문에 집계간에 동기식 (a.k.a 메서드 호출) 상호 작용이 없어야합니다.

예에서 사용자 AR은 예약 AR에 예약 메시지를 보냅니다. 이 메시지는 비동기식으로 안정적인 방식으로 전송됩니다. 예약 AR은이 메시지를 처리하고 다른 사람이 이미 책자 인 경우 ReservationRejected 메시지로 회신합니다. 그렇지 않으면 ReservationConfirmed를 보냅니다. 이 메시지는 Person AR에서 처리해야합니다. 아마도 그들은 고객에게 보낸 전자 메일 또는 이와 비슷한 것으로 변형 될 또 다른 이벤트를 생성 할 것입니다.

모델에서 쿼리 데이터를 가져올 필요가 없습니다. 그냥 메시지. 예제가 필요하다면, Ncqrs 프로젝트의 "Messaging"브랜치의 소스를 다운로드하고 ScenarioTest 클래스를 살펴볼 수 있습니다. Blue Book의 Cargo 및 HandlingEvent 샘플을 사용하여 AR 간의 메시징을 보여줍니다.

귀하의 질문에 대한 답변이 있습니까?

+1

동기 처리를 강요하면 어떤 종류의 일관성 문제가 발생합니까? 그것은 단순히 나에게 확장 성의 문제가 될 것으로 보이지만 나는 뭔가를 놓칠 수 있습니다. –

+0

저장소 모델이 교차 집계 트랜잭션 저장을 지원하지 않는다고 가정했습니다. 그것이 지원된다면, 정상적인 메소드 호출이 괜찮을 것이라고 (적어도 일관성에 관한 한). –

+0

팻 헬 랜드 (Pat Helland)의 논문을 살펴본 후, 나는 어디에서 왔는지 알 수 있습니다. 이 특정 시스템에서는 거의 무한대의 확장성에 관심이 없습니다 (그래도 좋은 문제 일 것입니다). 구현 세부 사항으로 MSMQ를 사용하고 있습니다. 나는 MSMQ를 사용하는 2PC가 우리 시나리오에서 수용 가능하다고 믿는다. 나는 생각이 맘에 들고 생각에 음식을 주었다. –

관련 문제