イベントソースの集計ルートは、イベント調達リポジトリにアクセスできる必要がありますか?
-
04-10-2019 - |
質問
私はに取り組んでいます イベントソース アプリケーション /ドメインレイヤーで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つの理由で総根の個別です。
- ビジネスコンポーネントがデータベースとは別に予約オブジェクトをプルする場合があります。 (つまり、釈放された人は、誤った情報のために以前の予約が変更されました)。
- 予約を更新する必要があるときはいつでも、人と予約の間にロック競合があるべきではありません。
もう1つのビジネス要件は、人に一度に2回以上予約が行われることはないことです。このため、読み取り側のクエリデータベースのクエリを照会することは心配しています(CQRを使用し、最終的に一貫した読み取りデータベースがあるため)、ある程度の矛盾がある可能性があるためです。
集計ルートは、オブジェクトのIDでイベントソースのバッキングストアをクエリすることができますか(必要に応じて怠zy-ロード)?より理にかなっている実装の他の手段はありますか?
解決
まず第一に、あなたは本当にあなたのケースで本当にイベントの調達が必要ですか?私にはとても簡単に見えます。イベントソーシングには、利点と短所の両方があります。無料の監査証跡を提供し、ドメインモデルをより表現力豊かにしますが、ソリューションを複雑にします。
わかりました、この時点であなたはあなたの決定を考え、あなたはイベント調達にとどまることを決心していると思います。凝集体間のコミュニケーション手段としてのメッセージングの概念が欠けていると思います。で最もよく説明されています パット・ヘランドの論文 (ところで、DDDやイベントの調達についてではなく、スケーラビリティに関する)。
アイデアは、集計が互いにメッセージを送信して、何らかの行動を強制することです。集合体間の同期(別名メソッド呼び出し)相互作用はあり得ません。これにより、一貫性の問題が発生するためです。
あなたの例では、人は予約メッセージを予約ARに送信します。このメッセージは、非同期で信頼できる方法で輸送されます。 ARの予約はこのメッセージを処理し、他の人がすでに予約している場合は、Reservation Rejectedメッセージで返信します。それ以外の場合は、予約済みを送信します。これらのメッセージは、人ARによって処理する必要があります。おそらく、彼らはさらに別のイベントを生成し、顧客またはそのようなものに送信される電子メールに変換されます。
モデルにクエリデータを取得する必要はありません。ただメッセージング。例が必要な場合は、の「メッセージング」ブランチのソースをダウンロードできます NCQRS プロジェクトとシナリオテストクラスをご覧ください。 Blue Bookの貨物とHondlingEventサンプルを使用してARS間のメッセージングを示しています。
これはあなたの質問に答えますか?