We are family
I got all my sisters with me
Sister Sledge
Some things belong together, like Apple Pie and Ice Cream, or Sonny and Cher. And so it is with Entities and Value Objects (VOs) – some of them belong together.
Aggregates are groups of things that belong together. An Aggregate Root is the thing that holds them all together.
I will warn in advance, as I proof read this post, it was pretty complicated – while I have tried to simplify the concepts, I am not certain I have totally succeeded. Hopefully Aggregates will become more clear later in the series when I start exploring them in code.
A Simple Example
In all Object Oriented programming we are used to dealing with objects that have references to other objects, and in DDD it is no different. For example, our Customer may have a reference to the customer’s Orders.
An Aggregate is slightly different, where as Customers and Orders can exist in the system independently, some Entities and Value Objects make absolutely no sense without their parent. The obvious example following on is Orders and OrderLines.
OrderLines have no reason to exist without their parent Order, nor can they belong to any other Order. In this case, Order and OrderLines would probably be an Aggregate, and the Order would be the Aggregate Root
The rule of Cascading Delete is sometimes cited as a good way to tell if you have a group of Entities or VOs that should be an Aggregate – if the parent, in this case the Order, was deleted all other parts of that Aggregate below Order would be deleted too. So if it doesn’t make sense that a parent being deleted would also delete all children, then you don’t have an Aggregate, you just have a good old fashioned reference.
So What is the Point of an Aggregate?
Well the first and most obvious point of an Aggregate is that it operates to a large degree as one “thing”. Notably the Aggregate Root is the single Entity that controls access to the children.
Where you may have a Customer with operations like .UpdateToPreferredStatus and you may have an Order with .GetSumTotal – the OrderLines of an Order would not have any logic exposed outside of the Order Entity – in other words to add a new OrderLine, or to change an OrderLine, you would tell the Order to make the changes – Order.AddNewItem for example.
In this respect, Aggregates provide a clean pattern to keep logic where it really belongs.
Another aspect of Aggregate Roots is that they are the Entities that are dealt with by Repositories.
In our examples above, we would have a Customer Repository, and an Order Repository, but there would not be an OrderLine Repository. It is the responsibility of the Repository for the Aggregate Root to deal with persistence of all the children of that Aggregate.
Restrictions on Aggregates and Aggregate Roots
The main, and possibly obvious restriction on Aggregate Roots is, they must be Entities, and cannot be Value Objects. Back to the previous post, you will remember that Entities have Identity, and Value Objects do not – you could not ask a Repository to retrieve an Aggregate Root if it had no Identity.
Within an Aggregate, the other players can be Entities and VOs as the Domain dictates. For example, expanding our Order example further, the Aggregate may comprise the Order (Aggregate Root), the Order may have an OrderNumber (Value Object), some OrderLines (Entities), and a Shipping Address and Billing Address (Value Objects)
Entities can hold references to any Aggregate Root, but never to any other Entity or VO within the Aggregates. To access any other part of the Aggregate, you must navigate from the Aggregate Root.
How the component parts of an Aggregates are persisted is a matter for the implementation behind Repository, but if you were using an ORM like NHibernate for example, the changes are that the Value Objects would be NHibernate Components nested in their parent entity record and the Entities would be old fashioned mappings, each with their own table.
In Conclusion
Aggregates provide a logical grouping of Entities and Value Objects that belong together at all times. An Aggregate Root is the gatekeeper to the Aggregate. Each Aggregate is treated as a single unit for persistence purposes.
By logically grouping Entities and VOs in this way, we provide a mechanism to strictly manage a grouping of objects, and a way to allow us to treat a number of different Entities and VOs as one.