English 中文(简体)
Should an event-sourced aggregate root have access to the event sourcing repository?
原标题:

I m working on an event-sourced CQRS implementation, using DDD in the application / domain layer. I have an object model that looks like this:

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
}

With my understanding of DDD so far, both Person and Booking are seperate aggregate roots for two reasons:

  1. There are times when business components will pull Booking objects separately from the database. (ie, a person that has been released has a previous booking modified due to incorrect information).
  2. There should not be locking contention between Person and Booking whenever a Booking needs to be updated.

One other business requirement is that a Booking can never occur for a Person more than once at a time. Due to this, I m concerned about querying the query database on the read side as there could potentially be some inconsistency there (due to using CQRS and having an eventually consistent read database).

Should the aggregate roots be allowed to query the event-sourced backing store by id for objects (lazy-loading them as needed)? Are there any other avenues of implementation that would make more sense?

最佳回答

First of all, do you really really need event sourcing in you case? It looks pretty simple to me. Event sourcing has both advantages and disadvantages. While it gives you a free audit trail and makes your domain model more expressive, it complicates the solution.

OK, I assume that at this point you thought over your decision and you are determined to stay with event sourcing. I think that you are missing the concept of messaging as a means of communication between aggregates. It is described best in Pat Helland s paper (which is, BTW, not about DDD or Event Sourcing, but about scalability).

The idea is aggregates can send messages to each other to force some behavior. There can be no synchronous (a.k.a method call) interaction between aggregates because this would introduce consistency problems.

In your example, a Person AR would send a Reserve message to a Booking AR. This message would be transported in some asynchronous and reliable way. Booking AR would handle this message and if it is already book by another person, it would reply with ReservationRejected message. Otherwise, it would send ReservationConfirmed. These messages would have to be handled by Person AR. Probably, they would generate yet another event which would be transformed into e-mail sent to customer or something like that.

There is no need of fetching query data in the model. Just messaging. If you want an example, you can download sources of "Messaging" branch of Ncqrs project and take a look at ScenarioTest class. It demonstrates messaging between ARs using Cargo and HandlingEvent sample from the Blue Book.

Does this answer your question?

问题回答

暂无回答




相关问题
DDD - Returning entity in response to a service operation

I am new to domain driven development & have a simple question. If a service needs to generate some entity as a response to an operation then how should it be done? One of the ways is to inject ...

Domain Driven Design efforts in dynamic languages? [closed]

Are you aware of any DDD efforts in a dynamic language ? Practical resources on DDD tend to decrease quite dramatically when straying from enterprise-oriented solutions (a google search exluding C#, ....

Accessing domain objects in the view

If I don t want to expose the internal state of my Domain Objects, but I need to display them, I can think of three approaches. Which of these is the most "correct" (if any?). The "DTO/ViewModel ...

DDD screen cast question?

I wathced a screen cast on DDD by Greg Young the other day which spoke about persisting all state transitions of an object, instead of it s state when saved, then to load it "replay" all these ...

How to fluent-map this (using fluent nhibernate)?

I have two tables in my database "Styles" and "BannedStyles". They have a reference via the ItemNo. Now styles can be banned per store. So if style x is banned at store Y then its very possible that ...

热门标签