CQRS + 이벤트 소싱 아키텍처에서 Add / Create * 명령을 처리하는 방법


11

Event Sourcing과 함께 CQRS 패턴을 사용하여 첫 번째 응용 프로그램을 구현하고 싶습니다. 골재 뿌리 생성이 올바르게 처리되어야하는지 궁금합니다. 누군가 CreateItem 명령을 보낸다고 가정 해 봅시다. 어떻게 처리해야합니까? ItemCreated 이벤트를 어디에 저장해야합니까? 새로운 아이템의 첫 번째 이벤트로? 아니면 모든 항목을 집계하고 해당 이벤트 목록이 ItemCreated 이벤트로만 구성된 일종의 ItemList 엔티티가 있어야합니까?

Udi Dahan 은 집계 루트를 작성하지 말고 항상 일종의 페치 메소드를 사용 하도록 제안 합니다. 그러나 새롭고 확실하게 ID가 할당되지 않은 것을 가져올 수있는 방법. 나는 그 아이디어를 이해하고 있으며 새로운 객체는 0 개의 이벤트로 구성된 상태를 가진 객체라고 생각하는 것이 합리적입니다. 그러나 어떻게 사용해야합니까? 내 리포지토리에 고유 한 방법이 있어야합니까, getNewItem()아니면 대신 get(id)방법을 받아 들여야 Optional<ItemId>합니까?

편집 : 파고 얼마 후 배우를 사용하여 앞에서 언급 한 패턴의 흥미로운 구현 을 발견했습니다 . 작성자는 집계를 작성하는 대신 새로 작성된 UUID를 사용하여 일종의 저장소에서 집계를 검색합니다. 이 접근 방식의 단점은 일시적인 불일치 상태를 허용한다는 것입니다. 또한 delete그러한 접근 방식으로 방법을 구현할 수 있는지 궁금합니다 . 삭제 된 이벤트를 집계의 이벤트 목록에 추가하기 만 하시겠습니까?


1
Udi의 포스트 타이틀이 오도 된 것으로 보입니다. 자신처럼 IMHO는 소리 진짜 목적은 갓 만든 액세스 라우터는 항상 방법으로, 다른 장소에서 접근 할 수 있어야한다는 것입니다 그 새로운 AR가 작성 될 필요가 있다고 결정 누가 어떻게 / 왜 / 약 캡처 컨텍스트. 그 밖의 모든 것은 특정 구현 (NHibernate?)이 관리하기 쉽게 만드는 방법에 관한 것입니다.
— Darien

2
참고로 언급하고있는 Udi Dahan 기사는 그의 조언이 이벤트 소싱에 적용되지 않을 수 있다고 구체적으로 설명합니다. udidahan.com/2009/06/29/dont-create-aggregate-roots/…
— EZ Hart

답변:


13

Udi의 게시물에 나오는 아이디어는 얇은 공기에서 어떤 종류의 항목도 나타나지 않는다는 것입니다. 항상 (거의) 무언가, 또는 더 구체적으로, 일부 도메인 작업이있어 ​​항목이 생성되었습니다. 실제로 사이트에 등록한 방문자로부터 태어난 사용자에 대한 Udi의 예와 같습니다. 이 시점과 제한된 컨텍스트에서 방문자는 자신의 IP 주소로 검색되는 집계 루트입니다. 그런 다음이 방문자는 Register 라는 도메인 작업을 통해이 시점에서 사용자 인 새 "항목"을 만듭니다 . 이전 단계도 마찬가지입니다. 이는 또 다른 경계 컨텍스트입니다. Referrer는 AR입니다. AR은 URL로 검색되며 방문자가 태어난 BroughtVisitorWithIp 라는 도메인 작업 이 있습니다.

우디뿐만 아니라 삭제에 매우 잘 쓴다 : http://www.udidahan.com/2009/09/01/dont-delete-just-dont/ . 주요 아이디어는 아무 것도 삭제하지 않는 것입니다. 캡처하려는 도메인 작업은 항상 뒤에 있습니다. 주문이 삭제되는 것이 아니라 취소되는 것처럼. 읽어보세요. 아주 좋은 게시물입니다.

DDD, 특히 이벤트 소싱을 수행하는 두 계정의 주요 요점은 직접 CRUD 작업을 수행해서는 안된다는 것입니다. 실제로 데이터를 삽입, 업데이트 또는 삭제해야하는 상황에 처해 있고 그 뒤에 도메인 작업이없는 경우 DDD 및 이벤트 소싱이 해당 컨텍스트에 적합하지 않을 수 있습니다 . 단일 경계 컨텍스트가 하나의 원칙을 준수하는 한 원하는대로이 두 가지를 자유롭게 결합 할 수 있습니다. 이런 식으로 CRUD 스타일 경계 컨텍스트는 데이터베이스에서 일부 행을 작성할 수 있으며, 이는 다른 경계 컨텍스트에서 엔티티 및 집계 루트가되므로 AR을 검색하고 작성할 필요가 없습니다.


2
"아마도 DDD와 이벤트 소싱은 그 제한된 맥락에 적합하지 않습니다." 당신은 DDD의 요점을 올바르게 얻습니다. 사탄의 영광을 위해서만 모든 경우에 구현되어서는 안되며 불확실한 규칙으로 가득 찬 복잡한 영역을 다루어야 할 때에 만 구현해야합니다. 개인적으로 요구 사항이 논리에 의해 좌우되지 않는 합법적 인 소프트웨어를 위해했습니다.
— Yegor Chumakov

2
"한정된 문맥" 에 대해이 문장 만 +1합니다 . :)
— Songo

2
+1 '추가'와 '만들기'동사의 사용은 좋은 오래된 테이블 형식 데이터베이스와의 상호 작용 측면에서 여전히 도메인에 대해 생각하고 있음을 강력히 암시합니다. 도메인 / 바운드 컨텍스트를 모르면 이것이 적절한 지 말할 수 없습니다. 지속성을 무시하고 도메인에 고유 한 명령 및 이벤트 (일명 INTENTIONS 및 OUTCOMES)에 중점을 둔 후 상태를 유지하는 방법에 대해 걱정하십시오.
— Matt

" '추가'와 '만들기'동사를 사용하는 것은 좋은 오래된 테이블 형식 데이터베이스와의 상호 작용 측면에서 여전히 도메인에 대해 생각하고 있음을 강력하게 암시합니다." '뭔가 추가'버튼이 큰 UI 디자인이 있다면 슬프게도 그 의도입니다. 말 그대로 새로운 것을 추가하십시오. 나는 일반적으로 당신에 동의하지만, 우리는 여기서 데이터베이스 수준을 이야기하고 있지 않습니다. 때로는 Add 또는 Create가 실제로 올바른 단어입니다.
— designermonkey

1
@designermonkey UI에 해당 버튼이 있으면 실제로 그 뒤에 도메인 작업이 있습니까? 그러나 10 배 중 9 회는 해당 컨텍스트에서 복잡한 도메인 작업이 필요하지 않습니다. 그리고 순수한 CRUD 연산은 순수한 CRUD 연산이므로 처리해야합니다. 도메인 모델의 복잡성이 필요한 경우에만 사용해야합니다. 따라서 다른 디자인 원칙을 가진 다른 경계 컨텍스트.
— Tuukka Haapaniemi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.