1

I'm currently designing a DDD system, and it is a reference implementation. The reference is a big ball of mud. I'm finding myself spending a fair amount of time determining aggregate roots and the relationships to other aggregates. Have you ever tried making everything an aggregate root and then refactoring to small aggregates? No one is going to design their aggregates correctly the first time, so why not start really small and build to small in comparison to starting large and breaking down.

This may seem like a common sense observation, but it wasn't to me; I've designed several DDD systems and I always start with big aggregates. I do know that big aggregates are a common anti-pattern and design flaw in DDD.

This question may seem subjective but refactoring is an objective practice. How you refactor, is the subjective part. So can we be objective about how we begin?

1 Answers1

5

Small is beautiful. This applies to aggregates as well.

According to Evans, an aggregate is:

A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the AGGREGATE, designated as the root. A set of consistency rules applies within the AGGREGATE’S boundaries.

This definition bears indeed the danger of viewing the "unit" too large. After all, according to this definition a whole domain could be viewed as some kind of unit for the purpose of data changes. Fortunately in practice, nobody takes it to this extreme and flawed viewpoint.

What is missing, is that the "units" should also be minimalistic: this avoids a lot of unnecessary couplings of entities with aggregate roots with a view to common OO design principles (Principle of least knowledge, single responsibility principle, interface segregation principle, ...).

So I have much sympathy with the idea of starting with every entity an aggregate. However, using blindly this other extreme might loose some of the benefits of aggregates and be costly in terms of refactoring. I'd therefore advocate some more nuance: start making every entity an aggregate unless there are justified reasons to absolutely not do so. Typical mistakes, such as including an entity in an aggregate because it's somehow referenced in the root and nowhere else, should of course not be considered as a valid reason.

Christophe
  • 81,699