2017-02-09 1 views
0

그래서 집계 루트에서 명령을 실행하고 명령 결과로 약 10 개의 이벤트가 발생했습니다. 이 이벤트는 내부 이벤트이므로 외부 시스템에서이 이벤트를 집계해야하므로 프로젝션을 결정했습니다 (기본적으로 프로젝션 읽기). 10 개의 이벤트 (내부)에서 1 개의 이벤트 (외부) 로의이 투영을하기 위해 비즈니스 규칙 (이벤트 병합과 관련된 비즈니스 규칙)을 적용해야합니다. 이 규칙은 도메인의 일부인 것처럼 보이지만 내부 이벤트의 계획을 세우므로 여기에 어디에 넣어야합니까?CQRS 모델 프로젝션 읽기 - 비즈니스 로직

기본적으로 프로젝션 로직은 도메인의 일부이므로 집계 내에 유지하고 프로젝션이 만들어진 코드에서 호출해야합니까?

UPDATE

그래서, 하나 개의 집계 루트 안에, 내가 예를 들어,이 CarCreated (Id), CarSeatColored (Red), CarWashed (CarWashed)와 같은 모든 집계 루트 엔티티를 통해 확산되는 하나의 명령 (aggregate.createPaint 및 washatsametime (id, red))에 대한 응답으로 3 이벤트 (내부)) 등 (이 모든 3 가지 이벤트는 단일 명령으로 인해 발생합니다.) 외부 시스템은 하나의 외부 이벤트를 CarMaintainenceDone (ID, repainted = true, washed = true, somevalue = 22)으로 수신합니다.

지금, 나는이 CarMaintainenceDone 이벤트를 만들기 위해 몇 가지 복잡한 논리가있는 경우 (같은 경우 (색상 == 빨간색 다음 프로젝션 someValue와의 == 22 그렇지 않으면 44) -이 투사 코드에서 이동 또는 도메인의 일부가되어야

업데이트 2

나에게 이것은 단지 예를 때문에 그냥 도메인을 모델링하는 방법을 무시하는 당신에게 새로운 예를 제공하기 위해 노력하자. 당신이 볼 수 있듯이

우리는 단지 거기에있다 승수를 포함 AggregateRoot이 올바른 이름으로 물건을 부르십시오. 우리가 곱셈을 할 때 우리는 먼저 내부 상태를 설정하고 ObjectAHasSetParam 이벤트를 내보내는 로직을 가진 ObjectA에 정수 1을 보냅니다. ObjectB도 마찬가지입니다. 마지막으로 ObjectC는이 모든 이벤트를 수신하고 paramsHasBeenSet에서 실제 곱셈을 수행합니다. 이 경우 이벤트 저장소에서

내가 이벤트의 목록을 보존하는 것입니다 :

[ObjectAHasSetParam , ObjectBHasSetParam , ObjectCHasMultiplied ] 

내 여기 지점되었다 : 나는 과정에서 하나이 모든 이벤트를 방출하는 경우 - 상태를 그 다른 사람 업데이트 것 아마도이 3 가지 사건은 오직한데 만 의미가 있기 때문에 일치하지 않을 수 있습니다. 그래서 프로젝션과 같은 것을 만들고 싶었던 것입니다.하지만이 경우에는 이벤트 대신 이벤트 목록을 함께 게시해야합니다.

class AggregateRoot{ 
    Multiplier ml; 

    void handle(MultiplyCommand(1,2)){ 
     ml.multiply(1,2); 
    } 
} 

class Multiplier{ 
    ObjectA a; 
    ObjectB b; 
    ObjectC res; 

    void multiply(1,2){ 
     a.setParam(1); 
     b.setParam(2); 
     publish(paramsHaveBeenSet()); 
    } 
} 

class ObjectA{ 
    int p; 

    void setParam(1){ 
     p = 1 + 11; 
     publish(ObjectAHasSetParam(12)); 
    } 
} 

class ObjectB{ 
    int p; 

    void setParam(2){ 
     p = 2 + 22; 
     publish(ObjectBHasSetParam(24)); 
    } 
} 

class ObjectC{ 
    int p1; int p2; 
    int res; 

    listen(ObjectAHasSetParam e1){ 
     p1 = e1.par; 
    } 

    listen(ObjectBHasSetParam e2){ 
     p2 = e2.par; 
    } 

    listen(paramsHaveBeenSet e3){ 
     res = p1 * p2; 
     publish(ObjectCHasMultiplied(288)); 
    } 
} 
+0

그건 이상한 문제입니다. 컨텍스트에 대한 자세한 정보를 제공해야합니다. 이벤트가 무엇인지, 병합 중인지 등을 알려줍니다. – VoiceOfUnreason

+0

"외부 도메인 이벤트"란 무엇입니까? –

+0

'CarMaintainenceDone' 이벤트가 발생하면 어떻게됩니까? 'Car' Aggregate는이 이벤트를 사용하여 앞으로 수신되는 명령에 대한 동작을 수정합니까? –

답변

0

외부 이벤트 개념이 있어서는 안됩니다. 이벤트는 집계에 의해 생성되고 동기식 읽기 모델, 사가 (sagas)에 의해 소비되거나 다른 시스템 및 마이크로 서비스가 원하는 곳에서 사용하는 외부 세계에 게시됩니다.

소비자 (예 : 무용담으로 구현 됨)는 비즈니스 규칙에 따라 해당 이벤트를 집계 한 다음 집계가 아닌 무언가를 수행해야합니다 (예를 들어 무용담은 새 명령을 생성 할 수 있음).당신은 자동차 정비는 Car 집계의 책임이라고 생각하면

UPDATE

(응답이 업데이트되는 질문), 다음 Car 집계는 이벤트를 발생한다. 이는 Car 집계의 향후 동작이 CarMaintainenceDone 이벤트의 영향을받는 방식에 따라 다릅니다. 이 특정 컨텍스트에서는 코드를 더 간단하게 만들기 위해 Car 집계에서 이벤트를 생성합니다.

+0

CarMaintainenceDone이 실제로이 3 가지 이벤트를 투영 한 것입니다. 그래서 당신은 근본적으로 말하자면, 비록이 3 가지 이벤트의 투영 일 뿐이지 만, 동일한 집계 (자동차)로부터이 CarMaintainenceDone 이벤트를 발생시켜야한다고 말하고 있습니까? 이벤트 소싱을 사용하기 때문에이 3 개의 이벤트는 이벤트 저장소에 저장됩니다. CarMaintainenceDone은이 경우 외부 고객에게 브로드 캐스트되어야하는 이벤트입니다. – bojanv55

+0

"외부 이벤트 개념이 있어서는 안됩니다."맞지 않습니다. 내 대답을 보라. – plalx

+0

@plalx 제 견해로는 모든 이벤트가 이벤트 저장소에 보존됩니다. 그런 다음, 이러한 이벤트는 원하는 모든 소비자에게 외부 세계에 공개됩니다. 이벤트 애그리 게이터가있는 당신의 이상은 흥미 롭습니다. 이 "집계 된 이벤트"가 이벤트 저장소에 지속됩니까? –

0

이벤트 모델, 내부 이벤트 (BC 내에서만 볼 수 있음) 및 외부 이벤트 (외부 세계에 게시 됨)가 자주 있습니다. 당신은 모든 것을 외부로 만들기로 결정할 수 있지만 모든 것을 버전화해야합니다.

내부 이벤트 대 외부 이벤트에 대한 자세한 내용은 Patterns, Principles, and Practices of Domain-Driven Design book p.408에서 확인할 수 있습니다 (링크에서 조금 위로 스크롤).

예상치는 외부 이벤트을 게시 할 책임이 없습니다. 일반적으로 메시징 인프라에서 외부 이벤트를 게시하는 응용 프로그램 서비스 계층에서 내부 이벤트 처리기를 등록하는 것이 일반적입니다. 이 프로세스를 활용하여 이러한 이벤트를 모아서 하나의 외부 이벤트를 게시 할 수 있습니다.

집계가 수행되는 방법은 사용자가 결정할 수 있지만 내부 이벤트를 동 기적으로 발생시킬 수 있고 처리기가 일반적으로 단일 스레드이므로 처리기에 첫 번째 이벤트를 수신 할 때 상태 머신을 설정하면됩니다 마지막으로 수신 할 때까지 집계 한 다음 메시지 버스에 게시합니다.

메시징 인프라가 이벤트 저장소와 동일한 트랜잭션에 참여할 수없는 경우 커밋 된 이벤트를 순서대로 읽는 추가 프로세스가있을 수 있으며 위와 동일한 작업을 수행 할 수 있습니다.

다른 대안은 소비자가 집계를 처리하도록하는 것입니다. 이는 소비자가 "CarMaintenanceDone"의 의미를 거부 할 수 있다면 올바른 접근 방법이 될 수 있습니다.

마지막으로 집계 자체에서 추가 이벤트를 게시 할 수도 있습니다. 이 이벤트는 AR 자체에서 활용할 수는 없지만 가끔 실용적인 것만 수행하는 것이 좋습니다 (읽기 모델에서 사용하는 데이터 만 사용하여 이벤트를 풍부하게하는 것과 같습니다). 이 접근법은 더 많은 이벤트가 추가되는 경우 논리를 변경하지 않아도된다는 장점이 있습니다.

+0

예.이 모든 것을 더 잘 이해하지 못했습니다. 마지막 파트에서 언급 한 것처럼이 외부 프로세스를 사용하면 실제로는 외부 시스템에 대한이 새로운 이벤트에 이벤트를 투영하는 것입니다. 또한 비즈니스 로직의 일부를 CQRS의 Q 부분으로 생성해야하는 것으로 보입니다. – bojanv55

+0

투영 재개를 위해 "이벤트 집계의 이벤트 게시"가 어떻게 작동합니까? 이 이벤트 집합에 대한 적절한 방법은 사가 (Saga)가 명령을 작성하는 것이라고 생각합니다. –

+0

@ bojanv55 저는 이것을 프로젝션이라고 부르지 않을 것입니다. 내부 이벤트 스트림을 외부 이벤트 스트림으로 변환하는 이벤트 프로세서입니다. 그것은 투영과 다른 목표를 가지고 있으며 Q 부분에있는 것으로 간주되지 않습니다. – plalx

1

외부 시스템 CarMaintainenceDone으로 한 외부 이벤트를 수신하도록 기대 (다시 칠 이드 = TRUE, 세정 = TRUE, someValue와 = 22);

아! 짧은 대답은 프로세스 관리자입니다.

더 이상 답을 얻으려면 지금 두 개의 집계가 있어야합니다. 그들 중 하나는 차의 상태를 추적하고 있습니다. 다른 하나는 과정을 추적하고 있습니다.

어딘가에 다른 집계가 숨겨져 있다는 큰 힌트가 있습니다. CarMaintenanceDone 이벤트가 발생했습니다.이 이벤트는 생성을 담당하는 집계가 없습니다. 모든 이벤트는 이벤트를 생성하는 "집계"어딘가에 있습니다.집합체는 실세계 또는 현실 세계의 프록시 (HttpRequestReceived) 일 수도 있고 다른 제한된 컨텍스트의 디지털 것일 수도 있습니다. 그러나 그 사건은 여러분에게 뭔가 어딘가에서 국가가 바뀌 었다고 말하고 있습니다.

즉, 유지 관리시기에 대한 규칙을 알고있는 집계가 있습니다. 정보 자원, 일의 통나무이다. CarWashed이 게시되면 (자동차 또는 세탁기 등으로) CarWashed 이벤트에 가입 한 이벤트 처리기가이를 알리기 위해 유지 관리 집계에 명령을 보냅니다. 유지 관리 집계는 자체 단계를 업데이트하고 논리를 실행하며 모든 개별 단계가 고려 될 때 MaintenanceCompleted 이벤트를 게시합니다.

프로세스와 유사한 대부분의 작업은 집계로 구현할 수 있습니다. 이상한 점은 "명령"이 이벤트 처리기처럼 보이는 경향이 있다는 것입니다. 그러나 관찰 된 각 이벤트에 응답하여 상태 시스템이 어떻게 변경되었는지 설명하는 자체 기록 (관찰 한 내용을 기반으로 함)이 있습니다.

프로세스의 복잡성에 따라 두 개 이상일 수 있습니다.

Rinat Abdullin은 자주 언급 한 introduction to process managers을 작성했습니다.

집합체와 프로세스 관리자 사이에는 명확한 구분이 없습니까? 나는 프로세스 관리자가 응용 서비스 세계에서 조정하고 살고,받은 명령에 따라 적절한 명령을 집계에 보낼 것이라고 생각했습니다.

내가 본 것으로부터 - 아니, 그렇지 않습니다. 문학은 그렇게 명확하지 않습니다. 예를 들어

, Udi Dahan wrote

는 여기에 당신이 제대로 CQRS을하고있는 것을 알고 줄 수있는 강한 표시이다 : 당신의 집계 뿌리는 무용담이다.

사가, 여기는 프로세스와 동일합니다.

+0

재미있는 아이디어입니다. 그래도 집합체와 프로세스 관리자 사이에는 명확한 구분이 없습니까? 나는 프로세스 관리자가 응용 서비스 세계에서 조정하고 살고,받은 명령에 따라 적절한 명령을 집계에 보낼 것이라고 생각했습니다. – plalx

+0

여기서 프로세스 관리자로 집계 (예 :'CarWashed' 핸들러)를 호출하는 이벤트 핸들러가 더 많습니다. – plalx

+0

나는 내 블로그에 더 이상 글을 쓸 계획이다. 게시 될 때 여기에 링크하겠습니다. – VoiceOfUnreason