C# – Event sourcing: merging aggregate root and projection

ccqrsdomain-driven-designevent-sourcing

I'm trying to get my head around the concept of event-sourcing based architecture.

From my understanding, the projection is the representation of a state in a given point of time; in fact – it's an aggregation of events which led to that state. The projection is being stored in a data store for purpose of querying.

Since both the aggregate and the projection are being "rebuilt" from stream of events, why shouldn't I merge them into single code piece?

I'd end up with a class that would be responsible for:

  • updating it's (internal) state based on applied events
  • creating new events when asked to change its state

For instance: the shop order. Assuming we have an infrastructure which stores the events, and dispatches them to the projections, then stores the projections

class Order: Aggregate {
    private Guid _id;
    private OrderState _state;
    private DateTime _dateCreated;
    private List<Item> _items = new List<Item>();

    public Order()
    {
        // used when loading from projection data store (de-serializing from JSON for example)
    }

    public Order(Guid id, IEnumerable<Item> items)
    { 
        // used when handling CreateOrder command,
        // uses Aggregate.PublishEvent which appends the event to the stream
        // the event dispatcher causes the event to be Applied as well
        this.PublishEvent(new OrderCreated(id, items));
    }

    public void Apply(OrderCreated ev) 
    {
        // event applied by event dispatcher, when reconstructing from events
        this._id = ev.Id;
        this._state = OrderState.New;
        this._items = new List<Item>(ev.Items);
    }

    public void Ship()
    {
        // used when handling ShipOrder command
        // incorporates business logic
        if (this._state != OrderState.Shipped)
        {
            this.PublishEvent(new OrderShipped(this._id));
        }
    }
}

Best Answer

Since both the aggregate and the projection are being "rebuilt" from stream of events, why shouldn't I merge them into single code piece?

Because they have different responsibilities.

The aggregate governs how the stream of events can be extended; at its core is the current collection of business rules governing the changes to this stream.

But the projections are views that support interesting query use cases. They have no interest in the business rules that govern what futures are possible, but only in figuring out how to represent the past.

They are sourced the same way -- and you may want to use common components for extracting the history from the book of record -- but the data structures used to support the use cases are likely to be different.

For example, if you have a use case where you need to query the relationships among the entities in your domain, you're probably going to want to service those queries from a graph database, rather than from an event store. Horses for courses.

Related Topic