Search code examples
eventsentitydomain-driven-designdomain-events

DDD: Entity with collection of value objects - One event or multiple?


Imagine an instance where we have an entity that has a collection of value objects.

If we were to add (say the domain concept is to assign) an additional record value object to the collection we would have something like:

entity.assign_record(...)

that would raise a:

class RecordAssignedEvent(...)

Straight forward.

Now imagine a situation where the invariant requires that an entire collection needs to be replaced. Let's say an assign method would now replace all the current records in the entity.

ie.

entity.assign_records(list <records>)

Would it be better to raise a single event:

class RecordsAssignedEvent:
    contains details of all records updated

or create a separate event per assigned record, then publish the collection together:

class RecordAssignedEvent(...)

My concerns are:

  • The single RecordsAssignedEvent will contain a lot of data... imagine 10 records being assigned? 100?
  • My domain events only contain primitive types. But if I raise as a single event, I'll be forced to create some DTO or similar to include as a collection. That DTO now needs to be available to any subscriber of the event. If I raise multiple events I can easily continue to limit to primitives.

In the DDDSample app there is a similar scenario where a Cargo has an itinerary made up of a number of legs (in this case the collection itself is a value object made up of value objects):

https://github.com/citerus/dddsample-core/blob/master/src/main/java/se/citerus/dddsample/domain/model/cargo/Cargo.java

Is there any guidance in these situations on the granularity of domain events?


Solution

  • Is there any guidance in these situations on the granularity of domain events?

    If you are looking for guidance about domain events, event-sourcing is a good search term to use: people who store their domain state in a stream of events spend a lot of time worrying about things like granularity.

    Broadly, having multiple domain events associated with a single transaction is common. In other words, you shouldn't hesitate at all to consider multiple domain events when that model is a better fit for your domain than a single event.

    A commonly discussed example is a "trade book", where we are matching up buy and sell orders. A single large sell order might close several different buy orders, and it is a natural fit with the language of the domain to be firing different events for each of the orders closed.

    In complex processes, it is often useful to be able to back trace the graph of events; C was caused by B was caused by A. The work to perform an analysis may be considerably simpler if we don't have to dig around in B trying to figure out which part of B was the cause of C.

    A number of the same motivations for cohesion in our source code also applies to event design.

    That said, you normally want domain reasons for multiple domain events, not mechanical reasons. If big, inconvenient to serialize graph of information really is a single atomic change in the language of your domain, then you really should do the work of designing the appropriate schema for it, rather than taking the shortcut of carving the information along arbitrary boundaries so that the data will align with your arbitrary schema conventions.

    aka "It depends".