4

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));
        }
    }
}
  • Using your order above, consider a searchable list of orders. That's probably something you want to display, but nothing an aggregate needs to care about. And trying to shoehorn it into an aggregate will make it needlessly complicated (versus mapping events directly to SQL updates to generate your searchable view, for example). – Kasey Speakman Feb 1 '17 at 23:38
3

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.

0

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 we speak about CQRS, you must to create (at least) two separate objects:

CQRS is simply the creation of two objects where there was previously only one (Greg Young)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.