Events vs Commands for aggregate constructors

Hello,

Following some examples I saw that the aggregate’s constructor normally receive a command. I am firing a “created” domain event in the constructor but that leaves the aggregate in an non valid state. I need some external data to properly construct an instance of my aggregate, and some of these data are constant along the aggregate life cycle. Processing the command and only firing the domain events force my to have null and non final values.

could I use a factory method to process the command and receive the event in the aggregate constructor?

following the previous idea, is there a way to use an snapshot event in a constructor?

Thank you.

Some things to keep in mind:

  1. The state kept in the (command side) aggregate should be limited to that which is required to enforce domain logic.
  2. You could consider using an (immutable) value object for the final state instead of final variables. It is true that the value object will be null until the event handler processes the event, but of course the event will always be replayed through your aggregate so the state will always be the first bit to be included. With this approach, you would simply include this most basic invariant in all the non-constructor command handlers:
    Assert.state(myImportantValueObject!=null, "The very important value object is missing")
  1. The state kept in the (command side) aggregate should be limited to that which is required to enforce domain logic.

For example, if I am creating an account and the command and event hold the nickname of the account (only input validation), I should not store that in a command aggregate attribute, is that what you mean?

  1. You could consider using an (immutable) value object for the final state instead of final variables. It is true that the value object will be null until the event handler processes the event, but of course the event will always be replayed through your aggregate so the state will always be the first bit to be included. With this approach, you would simply include this most basic invariant in all the non-constructor command handlers:
    Assert.state(myImportantValueObject!=null, "The very important value object is missing")

For me is a little strange that the constructor initialises the class and fires and event, I am not mutating the state in any other command handler(should I?). do you recommend to use command aggregates as state machines? (e.g. pending, created, deleted…)

Hi Victor, Troy,

Troy is giving you the right hints, but some background might help you out understanding why he’s sharing them.
I am assuming your planning to both do CQRS and Event Sourcing in your application.

Troy in point one states that your aggregate should only contain state to enforce domain logic.

This stems from the fact that the Aggregate is your Command Model in the CQRS diagram, which should make decisions whether a certain action (command) may be handled or not. It of course will need some information to perform that decision, which in general is the only thing you store as state in an Aggregate.
So your summed up explanation is correct. If a command sets the nickname of an account, but that nickname is never used to make decisions in other command handlers, then you do not need that state.

Now over to the second point. Yes, it is definitely not intuitive at first that a constructor does not set any fields of your aggregate. If you are however planning to Event Source your aggregates, the events should be the source of the state of your aggregate. That thus rules out any setters in command handling functions, as that are not events which have happened. So in general, you would have command handling constructors/functions which decide whether that command is valid to be acted upon. If that is the case, you notify the world that that decision has been made by publishing an event. That event will then be the source of your aggregate.

I hope this helps you out some more Victor. Do not hesitate to ask further questions if things are still unclear!

Cheers,
Steven

Thank you so much,

The event handler at the constructor is going to set at least the initial state of the instance doing that is the only command handler that mutates/initiates the aggregate.

  • should I set the Id in the constructor command handler or wait for the event and be nullable?
  • the aggregate instance is visible to receive further commands after the constructor of after the creation event handler?
  • as Troy Hard said, should I use to nulls to determine the state of my aggregate? how this play with replays and snapshots? could that lead to incorrect invariants?
  • Troy used Spring or Axon Assert, that throws and exception on fail. do you recommend to use exceptions on events to deal with failure checking invariants?

Sorry for the amount of questions, this is the first time I try to design a system in this way. Aggregates seems really different (command receivers, event listeners, state machine) vs cluster of domain objects that can be treated as one.

Hi Victor,

Like I said, it’s fine to ask questions. That’s what this forum is for.

Thank you so much,

The event handler at the constructor is going to set at least the initial state of the instance doing that is the only command handler that mutates/initiates the aggregate.

Your first comment however puts me off again. Maybe a code snippet would clarify in this space if I don’t understand you correctly.
Any how, if you’re going to do Event Sourcing, so use the EventSourcingRepository for your Aggregates (this is Axon’s default by the way), then changing state in a command handler will end up with an exception.
So setting any fields in a command handler is out of the questions. That’s were the @EventSourcingHandler annotated functions are for.

The event you’d apply in your Constructor Command Handler, lets call it AggregateCreatedEvent, would be handled by an @EventSourcingHandler void on(AggregateCreatedEvent event) { ... } function and that is were you’d set any id’s/fields you can from the event.

  • should I set the Id in the constructor command handler or wait for the event and be nullable?

You should wait for the event sourcing handler of the event you publish in your constructor command handler to set the aggregate identifier.

  • the aggregate instance is visible to receive further commands after the constructor of after the creation event handler?

An aggregate will be visible if the UnitOfWork has rounded up the whole process of command/event handling. Only if everything succeeded, will the events be persisted. Once that’s happened other commands can be published against it.

  • as Troy Hard said, should I use to nulls to determine the state of my aggregate? how this play with replays and snapshots? could that lead to incorrect invariants?

That wholly depends on the decision making process you let your command handlers go through. If you want to ensure a field is not null when the command arrives, then a null check is more than valid. If you’d however want to ensure a certain value is greater than X, then your decision making process (read: the assertion) should be just that.

  • Troy used Spring or Axon Assert, that throws and exception on fail. do you

recommend to use exceptions on events to deal with failure checking invariants?

This depends on what kind of notice you want to give the command publisher. If you want to silently ignore it’s command, then a normal return; statement would suffice. If the command publisher however did something terrible in terms of the published command, then an exception might be in place.

Sorry for the amount of questions, this is the first time I try to design a system in this way. Aggregates seems really different (command receivers, event listeners, state machine) vs cluster of domain objects that can be treated as one.

Hope this helps you out further Victor!

Cheers,
Steven

Thanks Steven you are helping my a lot.

What I was trying to convey was that calling a constructor will to initialise all the attributes even if there is no sets inside. Before calling the constructor all the initial values are set to null, false or 0 (if there is other values, private var a = “default/initial”).

Hi Victor,

Aah, I catch your point with the Aggregate state fields now.
And no worries, we’re here to help!
Can I assume my response answered your questions sufficiently on how to tackle this?

Cheers,
Steven

yes, thank you