事件源聚合根是否应该访问事件源库?

时间:2010-05-25 16:07:36

标签: repository domain-driven-design cqrs

我正在使用应用程序/域层中的DDD进行event-sourced 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的理解,Person和Booking都是单独的聚合根源,原因有两个:

  1. 有时,业务组件会将Booking对象与数据库分开。 (即,由于信息不正确,已被释放的人之前的预订已被修改)。
  2. 每当需要更新预订时,不应该在人员和预订之间发生锁定争用。
  3. 另一项业务要求是,一次不能对一个人进行预订。因此,我担心在读取端查询查询数据库,因为可能存在一些不一致(由于使用CQRS并且最终具有一致的读取数据库)。

    是否允许聚合根通过对象的id查询事件源后备存储(根据需要延迟加载它们)?是否有任何其他实施途径更有意义?

1 个答案:

答案 0 :(得分:10)

首先,您真的需要事件采购吗?这看起来很简单。事件采购既有优点也有缺点。虽然它为您提供了免费的审计跟踪,并使您的域模型更具表现力,但它使解决方案变得复杂。

好的,我认为在这一点上你考虑过你的决定而且你决定继续参与活动。我认为你错过了消息传递作为聚合之间通信手段的概念。它在Pat Helland's paper中被描述得最好(也就是BTW,不是关于DDD或事件源,而是关于可伸缩性)。

这个想法是聚合可以相互发送消息以强制某些行为。聚合之间不能进行同步(a.k.a方法调用)交互,因为这会引入一致性问题。

在您的示例中,Person AR会向预订AR发送预约消息。该消息将以一些异步和可靠的方式传输。预订AR将处理此消息,如果已经由另一个人预订,它将回复ReservationRejected消息。否则,它会发送ReservationConfirmed。这些消息必须由Person AR处理。也许,他们会产生另一个事件,这个事件将被转换成发送给客户的电子邮件或类似的东西。

无需在模型中提取查询数据。只是消息。如果您想要一个示例,可以下载Ncqrs项目的“Messaging”分支的源代码,并查看ScenarioTest类。它使用来自Blue Book的Cargo和HandlingEvent示例演示了AR之间的消息传递。

这会回答你的问题吗?

相关问题