5

アプリケーション/ドメインレイヤーでDDDを使用して、イベントソースのCQRS実装に取り​​組んでいます。次のようなオブジェクト モデルがあります。

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
}

私のこれまでの DDD の理解では、次の 2 つの理由から、Person と Booking の両方が別個の集約ルートです。

  1. ビジネス コンポーネントが Booking オブジェクトをデータベースから個別にプルする場合があります。(つまり、リリースされた人は、誤った情報のために変更された以前の予約を持っています)。
  2. Booking を更新する必要があるときはいつでも、Person と Booking の間でロックの競合があってはなりません。

もう 1 つのビジネス要件は、一度に 2 回以上、Person に対して予約が発生しないことです。このため、(CQRS を使用し、最終的に一貫性のある読み取りデータベースを使用するため) 潜在的に不整合が発生する可能性があるため、読み取り側でクエリ データベースをクエリすることを懸念しています。

集約ルートは、オブジェクトの ID によってイベント ソースのバッキング ストアにクエリを実行できるようにする必要があります (必要に応じて遅延読み込みします)。より理にかなった実装の他の手段はありますか?

4

1 に答える 1

11

まず第一に、あなたの場合、本当にイベントソーシングが必要ですか? 私にはとてもシンプルに見えます。イベント ソーシングには、長所と短所の両方があります。これにより無料の監査証跡が得られ、ドメイン モデルがより表現力豊かになりますが、ソリューションが複雑になります。

わかりました。この時点で、あなたは自分の決定について熟考し、イベント ソーシングにとどまることを決意していると思います。集約間の通信手段としてのメッセージングの概念が欠けていると思います。これについては、 Pat Helland の論文(ところで、DDD やイベント ソーシングについてではなく、スケーラビリティについての論文) で最もよく説明されています。

アイデアは、集約が互いにメッセージを送信して何らかの動作を強制できるというものです。一貫性の問題が発生するため、集約間で同期 (メソッド呼び出しとも呼ばれます) の相互作用が発生することはありません。

あなたの例では、Person AR は予約 AR に予約メッセージを送信します。このメッセージは、非同期で信頼できる方法で転送されます。Booking AR はこのメッセージを処理し、すでに別の人が予約している場合は、ReservationRejected メッセージで応答します。それ以外の場合は、ReservationConfirmed を送信します。これらのメッセージは、Person AR で処理する必要があります。おそらく、彼らはさらに別のイベントを生成し、それが顧客に送信される電子メールなどに変換されるでしょう。

モデルでクエリ データを取得する必要はありません。メッセージだけ。例が必要な場合は、Ncqrsプロジェクトの "Messaging" ブランチのソースをダウンロードして、ScenarioTest クラスを参照してください。Blue Book の Cargo と HandlingEvent サンプルを使用した AR 間のメッセージングを示します。

これはあなたの質問に答えていますか?

于 2010-05-31T03:46:20.943 に答える