Saturday, October 18, 2008

Are Aggregates Practical?

My coworker Jörg Jenni from GARAIO reflects in his recent post on how his team is implementing aggregates. I worked with him and his team for a few months so I know how their current implementation looks like. To be honest I was one of the developers that had problems to follow the rules that come with aggregates.

From Evans, the rules we need to enforce include:
  • The root Entity has global identity and is responsible for checking invariants
  • Root Entities have global identity. Entities inside the boundary have local identity, unique only within the Aggregate.
  • Nothing outside the Aggregate boundary can hold a reference to anything inside, except to the root Entity.
  • Objects within the Aggregate can hold references to other Aggregate roots.
  • A delete operation must remove everything within the Aggregate boundary all at once
  • When a change to any object within the Aggregate boundary is committed, all invariants of the whole Aggregate must be satisfied.
Especially the "do not hold a reference from the outside to an object inside the aggregate" rule is very strict. Jörg suggests in his post to implement aggregate internals as private classes in the root class. With this approach sure you will not violate the rule anymore as the compiler enforces it. The problem is that at some point you will need access to these objects even if they are identified as conceptually internal. For example as a client I need a reference to these internals to show some information on a screen, to test the logic of the internal object or to execute some business logic that needs knowledge of data and behavior of objects in the aggregate.

Don't understand me wrong, I really would love to apply this pattern. The essence of aggregates to identify a cluster of objects that can be conceptually thought of as one unit is very important for managing complexity. But is it practical in our today's programming model? On the domain driven design discussion board I found an interesting discussion about aggregate boundaries between DDD adopters and Eric Evans. From the discussion I see that we're not the only ones that have problems with the implementation of aggregates. And what's interesting is that in the same discussion Mr. Evans wrote that he'll try to add a concrete example and that he we'll come up with some useful new insight - he didn't return to the discussion.

Does anybody has a real world example of aggregates? One that enforces all the rules?