CQRSで新しい集約ルートを作成するにはどうすればよいですか?


10

cqrsアーキテクチャで新しい集約ルートを作成するにはどうすればよいですか?この例では、最初の1つのAR1への参照を保持する新しい集約ルートAR2を作成します。

開始点としてAR1メソッドを使用してAR2を作成しています。これまでのところ、いくつかのオプションが表示されます。

  1. AR1の内部メソッドでは、リポジトリにアクセスできるドメインサービスを使用して、このオブジェクトをcreateAr2RootOpt1呼び出しnew AR2()てdb imediatellyに保存できます。
  2. 最初の集約ルートなどでイベントを発行できます。SholdCreateAR2Eventこれに反応してコマンドCreateAR2Commandを発行するステートレスサガがあり、それが処理されて実際に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ます。次に、イベントのSagawhoentリストAR1WasCreatedを作成し、作成するコマンドを生成しAR2ますCreateAR2Command

オプションno.1は非常に間違っています。そのようなドメインサービスをに挿入しないでくださいAggregateAggregates純粋である必要があり、イベントの生成以外の副作用はありません。

PS Aggregateオブジェクトのインスタンスの作成(プログラミング言語の意味で)との作成(必要に応じて誕生)には違いがあるため、私はのコンストラクターからイベントを発行しませんAggregatehandleメソッドからのみイベントを発行します(を処理する場合command)。


どういう意味AR1WasCreatedですか?それでいいのAR2WasCreated?また、ロジックを使用する場合、AR2WasCreated実際に作成される前にイベントを発行しますか?また、このイベントをAR1のイベントログに保存すると問題が発生します。これは、実際にはこのデータをAR1内で必要としないためです(AR1内のデータは変更されません)。
Bojan Vukasovic 2017

はい、3年後です。それは行くAR1WasCreated-> SAGA(A1が作成された場合はルールがあり、次にA2を作成する)-> CreateAR2Command-> AR2WasCreated
Bojan Vukasovic

@BojanVukasovic書いたとおりに機能して良かった:)
コンスタンティンガルベヌ

2

cqrsアーキテクチャで新しい集約ルートを作成するにはどうすればよいですか?

作成パターンは奇妙です。

Udi Dahanには、一般的な問題について、いくつかの便利な点があります集約ルートを作成しないでください。基本的なポイントは、その集計がどこからともなく出てくるわけではなく、それらがどのように表示されるかを説明するドメイン言語があり、ドメインモデルに取り込む必要があるということです。

ねじれる傾向があるのは、コマンドを処理しているドメインモデル内のエンティティが、トランザクションによって変更されるエンティティではないということです。それは間違いではありません。(エンティティに自分自身を変更するように依頼する場合と比較して)奇妙です。

2番目のアプローチも問題ありません。「実際にデータベースに保存せずに発生させるイベント」は「ドメインイベント」と呼ばれることもあります

基本的な考え方は、同じトランザクション内で、コマンドハンドラーがイベントを発生させ、それがバスに沿ってイベントハンドラーに移動し、2番目の集計がそれ自体を作成できるようにすることです。おそらく、コードのまとまりが多少良くなります。

注:イベントソースシステムでは、通常、この方法でイベントを使用しません。

イベントソースを使用する場合、ShouldCreateAR2Eventは最初の集約ルートの状態に影響しないため、イベントストアに保存されません。

注:通常、イベント名は過去形です-ShouldCrateAR2のスペルが間違っています。

はい、イベントを同期バスにスローしてリモートコードを実行しているだけの場合は、そのイベントを記録簿に保存しないでください。このスケールでの実装の詳細にすぎません。

それとも、これをイベントストアに保存する必要がありますか?

同じトランザクションで2つの異なるイベントストリームを変更しないでください。この作成がAR1への変更も表す場合、通常の答えは、このトランザクションでAR1を変更することであり、AR2を作成するコマンドの起動を担当するイベントへの非同期サブスクライバーを使用します。

べき等のコマンド処理は、ここで非常に役立ちます。


ご回答ありがとうございます。100%明確ではないもう1つのこと-後でAR2をAR1の引数として使用する必要がある場合、これをどのように渡すか-CQRSは、ARはクエリではなく書き込みのみに使用する必要があると述べているためです。しかし、私がAR1.doSmthn(AR2 param)作成する読み取りプロジェクションには必要な完全なデータがないため(AR2のみが完全なデータを持っているため)、使用する以外に選択肢はありません。
Bojan Vukasovic 2017

>「はい、リモートコードを実行するために同期バスにイベントをスローするだけの場合は、そのイベントを記録簿に保存しないでください。」何かが起こるためにプロセスが開始されたことを知っているという点で、それを保存することには真の価値があると思います。これにより、これが実際に完了したかどうかを追跡することもできます。しかし、それはユースケースに依存すると思います
Chaosekie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.