Search code examples
entitydomain-driven-designaggregateaggregateroot

DDD: Aggregates and Deletes


It's taken awhile but I feel I've started to build a good understanding of aggregates in DDD. Keep them small (An Entity with Value Objects whenever possible) and when containing multiple entities, ensure their reason to exist is to enforce some (transactional) invariant.

Where I come a bit undone is when it comes to the Remove or Delete side of things. Imagine a:

Thread, with Posts

For a long time I would mistake the 'has-a' relationship for an aggregate, but...

The requirement that a Post must have a Thread can be enforced via a factory method on the Thread to add a Post.

Then in lieu of any business rules that require it, they can be separate aggregates. For instance, if you were loading a list of threads, it doesn't make much sense to have to also load all the posts for each thread as well.

What about deleting a Thread though? It makes sense that removing a Thread means the Posts for that thread should go as well. But enforcing that a Post must be removed when its Thread is removed leads to them becoming a single Aggregate with Thread as the aggregate root.

This is just a representative example, but in many cases any 'has-a' relationship often implies something like the above. ie. the child should no longer exists if the parent is removed.

So, any advice on a situation when the only reason to seem to need an aggregate relationship between two entities is for delete/remove purposes?

My thinking at the moment?

  • You don't really delete a Thread. You make it inactive.
  • When a thread is made inactive, you obviously can't add any new posts (enforced through the factory method). Any posts that belong to the now inactive thread are also made inactive through eventual consistency?

Any other pearls of wisdom learned to ensure not mixing up a 'has-a' relationship with an aggregate root / child entity aggregate?


Solution

  • You don't really delete a Thread. You make it inactive.

    See also Don't Delete, Just Don't.

    Any other pearls of wisdom learned to ensure not mixing up a 'has-a' relationship with an aggregate root / child entity aggregate?

    I'd say that the most important lesson is this: if two pieces of information have to be kept immediately consistent with each other, then they have to be stored together <-- same database. In other words, the need for immediate consistency puts constraints not only on your domain model, but also on your data model.

    In business systems, "have to be consistent" is less frequent than you might expect, because the key motivation for "have to be" is "what is the cost to the business if they are not?"

    The classic example used here is orders vs inventory; we don't need to have reservable stock on the floor in order to accept a new order -- "backorder" is a real thing in the domain, and is often a better way of doing business than keeping everything immediately consistent.