Event Sourcing – Using Aggregate Roots with the Specification Pattern

aggregatecqrsdomain-driven-designevent-sourcing

I have a Aggregate Roots that use the event sourcing technique of being built from a series of events in a Repository. This is all great for when I just need to manage change of state etc, but when I come to using the Specification pattern to apply my app specific business rules, I am hitting a wall on what Entities to use, how to instantiate them etc etc.

I would want to run specific methods on my Repository, for example getProductByProductCode so I can check my current AR against it for uniqueness (simple example), but I am unsure how to do this, as my Repository is set up to get ARs by their ID from the event store.

I used to have a database backing my Repositories, now I only have an event store as I have no read models yet.

  • Has anyone done this before, and how did you do it?
  • Do I need a read model first?
  • Should I query the read model, then use a resulting ID to get the AR from the event store?
  • What if I need multiple AR results to be returned?

I am so confused as I thought I was doing it all the right way now as we need event sourcing, but I can't seem to marry up my old-school thinking with how to do it now it's event sourced 🙁

Best Answer

Repository is set up to get ARs by their ID from the event store.

That should suffice. If you need to query a collection of ARs from the repository you should use a specially designed Read model.

Put it another way, you are using CQRS. This means that you cannot query the Aggregate to check it's product code and it's natural that you cannot query the repository either, which basically its a collection of Aggregates.

Has anyone done this before, and how did you do it?

I create a fast, light, specially designed Read model that answers to this question only: bool isThereAlreadyAProductWithThisCode(string productCode).

Do I need a read model first?

Yes. See above.

Should I query the read model, then use a resulting ID to get the AR from the event store?

Only if you need to send commands to it. Aggregates have only command methods (no query method whatsoever).

What if I need multiple AR results to be returned?

Then create a new one or modify the above Read model to answer to this query.

I am so confused as I thought I was doing it all the right way now as we need event sourcing, but I can't seem to marry up my old-school thinking with how to do it now it's event sourced :(

It is hard because there are two leaps that you must take:

  1. CQRS: there is a write model that only receive commands (methods that return void). It does not have any query method. In DDD, this is the Aggregate, with its entry point, the Aggregate root. There is also one or more Read models. They have query methods that answer any question from the other layers (i.e. Presentation, Application, Infrastructure). They have also methods that update their persisted state when events happen but these methods are not to be used by the other layers. After the events are applied to all the Read models, they are discarded (not used any more by the write side). When a command arrives, the Aggregate is loaded from a Repository where its plain state was persisted when the last command was handled.

  2. Event sourcing: the write model, in DDD the Aggregate, has no plain persisted state. Every time a command arrives, the Aggregate is rehidrated by the Event store by new-ing an Aggregate's class and then applying all its own previous emmited events (there is an optimisation called snapshoting but it acts just like a cache and it should be avoided if not really necessary). There is no database containing the Aggregates state other than the Event store.

Related Topic