Here's how that looks like in a DDD world:
* An aggregate is responsible for encapsulating business rules and emitting events
* An aggregate is responsible for maintaining the validity of its own state (ensuring invariants are valid)
* When a command/request is received, the aggregate first rehydrates its current state by replaying all previous events
* The aggregate then validates the command against its business rules using the current state
* Only if validation passes does the aggregate emit the new event
* If validation fails, the command is rejected (e.g., throws CartMaxLimitReached error)
Example flow: Command "AddItemToCart" arrives
>> System loads CartAggregate by replaying all its events
>> CartAggregate checks its invariants (current items count < 10)
>> If valid: emits "ItemAddedToCart" event. If invalid: throws CartMaxLimitReached error
Here's how that looks like in a DDD world:
* An aggregate is responsible for encapsulating business rules and emitting events
* An aggregate is responsible for maintaining the validity of its own state (ensuring invariants are valid)
* When a command/request is received, the aggregate first rehydrates its current state by replaying all previous events
* The aggregate then validates the command against its business rules using the current state
* Only if validation passes does the aggregate emit the new event
* If validation fails, the command is rejected (e.g., throws CartMaxLimitReached error)
Example flow: Command "AddItemToCart" arrives
>> System loads CartAggregate by replaying all its events
>> CartAggregate checks its invariants (current items count < 10)
>> If valid: emits "ItemAddedToCart" event. If invalid: throws CartMaxLimitReached error