CQRS에서 새로운 집계 루트를 만드는 방법은 무엇입니까?


10

cqrs 아키텍처에서 어떻게 새로운 집계 루트를 만들어야합니까? 이 예에서는 첫 번째 AR1에 대한 참조를 보유하는 새로운 집계 루트 AR2를 작성하려고합니다.

AR1 방법을 시작점으로 사용하여 AR2를 만들고 있습니다. 지금까지 몇 가지 옵션이 있습니다.

  1. AR1의 내부 메소드는 리포지토리에 액세스하는 도메인 서비스를 사용 하여이 객체를 createAr2RootOpt1호출 new AR2()하여 dbmedia에 ly 저장할 수 있습니다.
  2. 예를 들어 첫 집계 루트에서 이벤트를 생성 할 수 있습니다. SholdCreateAR2Event그리고 이것에 반응하고 명령 CreateAR2Command을 내린 상태 비 저장 사가 (stateless saga)를 가지고 있고 실제로 처리되고 실제로 AR2를 생성하고 방출 AR2CreatedEvent합니다. 이벤트 소싱을 사용하는 경우 SholdCreateAR2Event첫 번째 집계 루트의 상태에 영향을 미치지 않으므로 이벤트 저장소에서 보존되지 않습니다. (또는 여전히 이벤트 저장소에 저장해야합니까?)

    class AR1{
        Integer id;
        DomainService ds;
    
        //OPTION 1
        void createAr2RootOpt1(){
            AR2 ar2 = new AR2();
            ds.saveToRepo(ar2);
        }
    
        //OPTION 2
        void createAr2RootOpt2(){
            publishEvent(new SholdCreateAR2Event());    //we don't need this event. Shoud it still be preserved in event store?
        }
    }
    
    class AR2{
        Integer id;
        Integer ar1Id;
    
        void handle(CreateAR2Command command){
            //init this AR with values and save
            publishEvent(AR2CreatedEvent());    //used for projections afterwards and saved inside AR2 event store
        }
    }
    
    class Saga{
        void handle(SholdCreateAR2Event ev){
            emitCommand(new CreateAR2Command());
        }
    }
    

이것을 수행하는 더 적절한 방법은 무엇입니까?

답변:


2

그 옵션은 없다고 생각합니다. 2는 작지만 중요한 수정 사항이있는 솔루션입니다. AR1목적으로 이벤트를 생성 AR2하지 말고 대신 AR1WasCreated이벤트 를 생성 해야합니다 . 이 이벤트는의 탄생을 표시하는 중요한 이벤트이므로 이벤트 저장소에 유지되어야합니다 AR1. 그런 다음 이벤트에 Saga대한 목록 AR1WasCreated을 작성하고 생성 명령을 생성하십시오.AR2 : CreateAR2Command.

옵션 1 번은 매우 잘못되었습니다. 이런 종류의 도메인 서비스를Aggregate . Aggregates사건 발생 이외의 부작용없이 순수해야합니다.

추신 : 나는 Aggregate프로그래밍 언어 의미에서 객체의 인스턴스를 만드는 것과의 생성 (원하는 경우 출생)이 구별되므로 의 생성자에서 이벤트를 생성하지 않습니다 Aggregate. handle메소드 에서만 이벤트를 생성합니다 (을 처리 할 때 command).


무슨 소리 야 AR1WasCreated? 그럴까요 AR2WasCreated? 또한 논리를 사용하면 AR2WasCreated실제로 생성되기 전에 이벤트 를 방출 합니까? AR1의 이벤트 로그 에이 이벤트를 저장하면 실제로 AR1 내부 에이 데이터가 필요하지 않기 때문에 문제가있는 것 같습니다 (AR1 내부의 아무것도 수정하지 않음).
보얀 부 카소 비치

3 년 후 그것은 간다 AR1WasCreated-> SAGA (A1 다음 A2를 생성 생성 된 경우 규칙이) -> CreateAR2Command-> AR2WasCreated.
보얀 부 카소 비치

@BojanVukasovic : 내가 쓴대로 작동해서 기쁘다 :)
Constantin Galbenu

2

cqrs 아키텍처에서 어떻게 새로운 집계 루트를 만들어야합니까?

창조 패턴은 이상하다 .

Udi Dahan은 일반적인 문제에 대해 다음과 같은 유용한 정보를 제공합니다 . 집계 루트를 만들지 마십시오 . 기본 포인트는 집계가 아무데도 나타나지 않으며 도메인 모델에서 캡처되어야하는 언어가 표시되는 방식입니다.

트위스트되는 경향은 명령을 처리하는 도메인 모델 의 엔티티가 트랜잭션에 의해 수정되는 엔티티 가 아닌 것입니다. 그건 잘못된 것이 아닙니다. 엔터티에 자신을 수정하도록 요청하는 경우와 비교하면 이상합니다.

두 번째 방법도 좋습니다. "실제로 데이터베이스에 저장하지 않고 발생시키는 이벤트"를 "도메인 이벤트"라고합니다.

기본 트랜잭션은 동일한 트랜잭션 내에서 명령 핸들러가 이벤트를 발생시키고,이 이벤트는 버스를 따라 이벤트 핸들러로 이동하여 두 번째 집계가 자체적으로 작성되도록합니다. 아마도 더 나은 코드 응집력을 얻을 수 있습니다.

참고 : 이벤트 소스 시스템에서는 일반적으로이 방법으로 이벤트를 사용하지 않습니다.

이벤트 소싱을 사용하는 경우 ShouldCreateAR2Event는 첫 번째 집계 루트의 상태에 영향을주지 않으므로 이벤트 저장소에 보존되지 않습니다.

참고 : 이벤트 이름은 일반적으로 과거 시제입니다. shouldCrateAR2의 철자가 잘못되었습니다.

예, 원격 코드를 실행하기 위해 이벤트를 동기 버스에 방금 던지는 경우 해당 이벤트를 기록부에 저장해서는 안됩니다. 이 규모의 구현 세부 사항 일뿐입니다.

아니면 여전히 이벤트 저장소에 저장해야합니까?

동일한 트랜잭션에서 서로 다른 두 개의 이벤트 스트림을 수정하지 마십시오. 이 작성이 AR1에 대한 변경 사항을 나타내는 경우, 일반적인 응답은이 트랜잭션에서 AR1을 수정하는 것이며 AR2 작성 명령을 실행해야하는 이벤트에 대한 비동기 가입자를 사용합니다.

dem 등원 명령 처리는 여기서 많은 도움이됩니다.


대답 해줘서 고마워요. CQRS는 AR이 쓰기 전용이며 쿼리하지 않아야한다고 CQRS는 명시하기 때문에 100 % 명확하지 않은 한 가지 더-나중에 AR1에 대한 인수로 AR2를 사용해야하는 경우이를 어떻게 전달해야합니까? 그러나 내가 AR1.doSmthn(AR2 param)만드는 모든 읽기 투영에는 필요한 완전한 데이터가 없기 때문에 사용하는 것 외에 다른 옵션 이 없습니다 (AR2만이 완전한 데이터를 가짐 ).
보얀 부 카소 비치

> "예, 원격 코드를 실행하기 위해 이벤트를 동기 버스에 방금 던지는 경우 해당 이벤트를 기록부에 저장해서는 안됩니다." 나는 그것을 저장하면 어떤 일이 일어나기 위해 프로세스가 시작되었다는 것을 알기 때문에 실제로 가치가 있다고 생각합니다. 이제 실제로 완료되었는지 추적 할 수 있습니다. 그러나 그것은 유스 케이스에 달려 있다고 생각합니다
Chaosekie
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.