Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
DDD: Aggregates and Aggregate Roots

Download the eBook of the Series so far …

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 or 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 Aggregate. To access any other part of the Aggregate, you must navigate from the Aggregate Root.

How the component parts of an Aggregate 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.

Previously:

1) Domain Driven Design: A Step by Step Guide
2) DDD: The Ubiquitous Language
3) DDD: Bounded Contexts
4) DDD: There Is No Database
5) DDD: Command Query Separation as an Architectural Concept
6) DDD: Entities and Value Objects
7) DDD: Where is the Code?
8) DDD: Download an eBook of the Series

Reference:

InfoQ Free eBook : Domain Driven Design Quickly
Domain-Driven Design: Tackling Complexity in the Heart of Software (Eric Evans)

Aggregates

del.icio.us Tags: DDD,Domain Driven Design,Practices and Principles


Posted 02-16-2009 2:50 PM by Jak Charlton

[Advertisement]

Comments

Kenny wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 10:44 AM

How far should you stretch this? I'm sitting in a project right now containing alot of classes all relevant to a single class.

A ResultSource contains several questions and "views". A question in it turns contains options. A "view" contains questions also, and severals other objects with child objects.

How far should an aggregate traverse?

Casey wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 10:54 AM

The simple answer is, as far as it can without violating the Cascading Delete rule.

If all these things would be redundant and need deleting when the parent was deleted then they form an Aggregate

For convnience you might be able to split them, but ultimately it will probably be more work

DotNetShoutout wrote DDD: Aggregates and Aggregate Roots - Casey Charlton - Insane World
on 02-16-2009 11:47 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Kenny wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 11:49 AM

Maybe i'm missing something but this seems incorrect. In my scenario the aggregate would be a customer. Each customer has several "resultsources" containing several questions and other objects. If we go by the cascade-delete rule the correct aggregate here would be customer. This would case each and every entity to bound to the customer, this seems wrong to me. I wouldn't want my customer entity to have methods to change something on a question, that should be the resultsource concern.

Or is it so that an aggregate can contain other aggregates? I've probably misunderstood something :)

on 02-16-2009 12:56 PM

DDD/ALT.NET Casey has written a bunch more in his DDD series since my last update 4) DDD: There Is No Database 5) DDD: Command Query Separation as an Architectural Concept 6) DDD: Entities and Value Objects 7) DDD: Where is the Code? 8) DDD: Download

Joe wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 3:28 PM

Could you explain with another example around building a forums system?  Would you have the forum be the aggregate root with children of threads and posts as children of threads?  I think this passes the cascading delete rule, but I don't think that alone dictates the forum should be the aggregate root (and I don't think you're really saying that either - just looking for clarification).  Or, would you aggregate these at all?  Forum might have methods like StartNewThread and Thread might have posts like ReplyToThread.  I could possibly see putting thread-related and post-related methods on the Forum class, but honestly that feels like it's expanding Forum's responbilities too far.  

Anyway, great series - looking forward to more!

Kenny wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 4:10 PM

Ye, Joe put it alot better than me :) That was what i was trying to say, where do you draw the boundaries.

Michael Hart wrote re: DDD: Aggregates and Aggregate Roots
on 02-16-2009 9:47 PM

While it's a useful heuristic for closely related parent-child relationships, I think it might be stretching it to call it a rule that you should go as far as you can not to violate. It's often acceptable for deletes to be resolved at a later time.

For many top-level domain objects, they contain too much responsibility to be considered part of the same Aggregate, even if there is a one-to-many relationship that you'd normally consider for a "cascading delete" (Evans gives the example of a Customer-Car relationship in a repair shop, with both these being Aggregate roots - technically if you deleted the Customer, you'd cascade the delete to the Car too - but this would be exceptional behaviour, it would be acceptable to allow for eventual consistency, and bundling everything up a Customer Aggregate would confuse the Car-specific behaviour).

I think in many cases it's the behaviour of the entities that really bring out the Aggregate concepts, and I'm sure this is what you meant when you said they'll become clearer as you proceed with the series. Evans really stresses that Aggregates are essential for enforcing the invariants of closely related groups of objects, so the integrity of the behavioural state is key here. If it's OK for the "cascading delete" (if it's actually needed - that is, are there even use cases where the object in question is deleted) to happen in a deferred manner (for example, as part of a separate transaction), then this heuristic wouldn't necessarily apply.

So in Kenny's example (albeit without any real knowledge of the domain), I'd be looking at the Customer invariants as probably separate from the ResultSources (whatever they are) - and perhaps "Questions" are a separate Aggregate again, depending on your use cases. Ask the question whether Customers are deleted as a normal course of action, and if so, then is it acceptable for the ResultSources to be deleted by a separate responsibility.

Jak Charlton wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 3:15 AM

The point is not whether they are or no deleted by a cascade delete, but whether in the case the root was, that they have absolutely no purpose or point to exist otherwise.

In the case of Order to OrderLines - the OrderLines *are* part of the Order, they just happen to be represented as a different thing to make operations easier.

You know the old OO rules on inheritance/polymorphism... "x IS A y"  ... well consider when trying to form aggregates the rule "is part of" ... that may help make the decision

In the case of an ExamPaper, the Questions are a part of it, if the Questions are never used elsewhere or in another way . The Results for the paper are not part of the Paper, and the Results are not part of the ExamCandidate. Results are also not a part of the ExamPaper nor are individual Resuls part of the Question

I'm not sure the forum example is a great one, it isn't something that would be ideally suited to DDD anyway, and having written a couple in the past, I know they are more about complex tree manipulation than much else ... but ...

The Threads are not a constituent part of a Forum - people would refer to Thread being in a Forum, not part of a Forum. The Posts may well be a part of a Thread.

So a very basic version of that form scenario would have 3 aggregates, User, Forum, Thread (containing Posts)

When deciding on Aggregates, bear in mind, this is a logical grouping of very intimately related parts.

Reflective Perspective - Chris Alcock » The Morning Brew #288 wrote Reflective Perspective - Chris Alcock » The Morning Brew #288
on 02-17-2009 3:39 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #288

Michael Hart wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 7:43 AM

"The point is not whether they are or no deleted by a cascade delete"

Not sure if this was directed at my comment, or the others - in the case of the former, this wasn't the point I was making. I was pretty much trying to follow your Rule of Cascading Delete - I did put it in quotes to indicate that it didn't need to be taken literally, but perhaps I should've been clearer with that.

"but whether in the case the root was, that they have absolutely no purpose or point to exist otherwise."

Now this relates more to the point I was trying to make and something I think doesn't ring true for high level domain concepts. I think the example that Evans gives (Customer-Car) is a perfectly fine violation of this "rule". The Cars in the auto-repair shop would have no purpose to exist without Customers, but they're still separate Aggregate Roots. And this is true of many systems that have Customers/Users/etc - this doesn't mean that you drive your system from a monolithic User Aggregate Root.

"this is a logical grouping of very intimately related parts"

Evans says as much and I find this a much better description, which is why I was trying to stress this over the heuristic regarding existence - that it's the behaviour and the context of these objects that really matter. Dependent existence is only one invariant - and it may be one that doesn't even come into play at all (ie, the Car can't exist without the Customer - but are there any use cases for the Customer being totally removed anyway? Even if there were, you'd expect it to be a rare occurrence - one that falls outside the bounds of our normal invariance enforcement - a Service could enforce this consistency, even if it's in a deferred manner)

What do you think?

Michael Hart wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 8:00 AM

As an aside, in the Forum example you gave - how does the Thread exist without the Forum that it's in and the User that started it? Isn't that in conflict with what you were saying with "they have absolutely no purpose or point to exist otherwise"?

Joshka wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 8:56 AM

Thanks for this series. Your overuse of bold text makes it harder to read this article. You might consider reducing the number or weight of the bolded search terms or perhaps only bolding them the first time that they are used.

Joe wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 9:18 AM

Thanks for the explanations all.  I'm resonating on Casey's statement that a forums app isn't really suited to DDD, and so it makes me wonder what makes an app suitable?  Perhaps that would be a good post to add to the series.  I'm assuming that you're talking about the modeling process here, since many of the design patterns/concepts still seem quite applicable (repositories, entities, value objects, and the like).

The reasoning about "being part of" vs. "being in" was helpful too.  I'm going to run with that and see where it takes me.

/jf

Jak Charlton wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 1:33 PM

@Michael

The Forum example isn't a great one, but Threads are not a constituent part of a Forum, for example it is conceivable that a Thread could be in more than one Forum, or be moved between Forums

@Joshka

I will see what I can do - apologies if it is a little hard to read on your screen, its ok on mine, but maybe I am used to it

@Joe

I will do another interlude post soon to explain where I see DDD being a good fit in it's entirety, and where it would be better to use some of the patterns but avoid the whole

Lance wrote re: DDD: Aggregates and Aggregate Roots
on 02-17-2009 3:56 PM

If wishes to add or associate an order to a customer, where should this operation/method reside?  Should there be an AddOrder method on the customer object?  Or should there be a repository method that associates them like an AddOrderToCustomer(int orderId, int customerId)?

I would think that the former option would allow one to avoid the anemic domain model anti-pattern and a customer repository would save the customer object with the order added to its orders collection after the addition, but I may be wrong.

Thank you.

Casey Charlton - Insane World wrote DDD: Services
on 02-17-2009 4:38 PM

There can be no word more common in development, and no word used for such a multitude of different things

Community Blogs wrote DDD: Services
on 02-17-2009 4:44 PM

There can be no word more common in development, and no word used for such a multitude of different things

Jak Charlton wrote re: DDD: Aggregates and Aggregate Roots
on 02-18-2009 2:57 AM

@Lance

Cross Repository operations like adding a Customer and an Order can be dealt with to ways:

1) as two operations - Add the Customer, then Add the Order (Customer can exist without Orders)

2) Using a UnitOfWork pattern martinfowler.com/.../unitOfWork.html

Fractured Bloughts » Software Development » Requirements and Use Cases wrote Fractured Bloughts » Software Development » Requirements and Use Cases
on 02-18-2009 7:55 AM

Pingback from  Fractured Bloughts  » Software Development    » Requirements and Use Cases

Lance wrote re: DDD: Aggregates and Aggregate Roots
on 02-18-2009 10:04 AM

Thank you for your response.  Assuming the customer exists already, how are you suggesting the order be added?  Does a customer class expose a method for adding orders and then once orders are added, the customer object is persisted?  Or is there some external service that associates the new order to the customer?  If the latter option is chosen, it renders the customer domain object anemic.

Jak Charlton wrote re: DDD: Aggregates and Aggregate Roots
on 02-18-2009 10:25 AM

@Lance

Customers and Orders wouldn't (almost certainly not) compose an Aggregate ...  so presuming they don't ...

Yes, a Customer would probably have a .AddNewOrder(order) or .AddNewOrder(orderId)

That decision is a bit of a trade off in how you reference the Orders later ... if you tend to have the Customer operate on them, or want to use lazy loading via the Customer, then passing the Order directly may be best ... if you want to keep a clean separation then the latter may be better.

Either way, removing the ability to add one entity to another on the entity itself would not make it anaemic ... removing all the other methods that actually do something would do that ...

Also consider whether you actually do .AddNewOrder ... or whether you use a Service that does .CreateOrderForCustomer(customer) ... which itself uses a factory for the Create and does the linking itself.

Again, when you get to implementation, there are very few absolutes... each situation and scenario is different ... many patterns will work - just aim towards the DDD principles as the objective.

Casey Charlton - Insane World wrote DDD: What Kind of Applications Is It Suited To?
on 02-18-2009 2:20 PM

In many conversations, and in many comments here, you hear phrases like “well that’s not really suited

Community Blogs wrote DDD: What Kind of Applications Is It Suited To?
on 02-18-2009 2:39 PM

In many conversations, and in many comments here, you hear phrases like “well that’s not really suited

Fractured Bloughts » Software Development » Requirements and Use Cases - part II wrote Fractured Bloughts » Software Development » Requirements and Use Cases - part II
on 02-18-2009 3:16 PM

Pingback from  Fractured Bloughts  » Software Development    » Requirements and Use Cases - part II

Casey Charlton - Insane World wrote DDD: The Repository Pattern
on 02-20-2009 3:30 AM

I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we

Community Blogs wrote DDD: The Repository Pattern
on 02-20-2009 4:12 AM

I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we

Casey Charlton - Insane World wrote DDD: Living In The Enterprise
on 02-21-2009 4:25 AM

No, not that Enterprise! The other Enterprise – the big amorphous one that organisation spent a fortune

Community Blogs wrote DDD: Living In The Enterprise
on 02-21-2009 4:48 AM

No, not that Enterprise! The other Enterprise – the big amorphous one that organisation spent a fortune

Insane World wrote DDD: The Repository Pattern
on 02-21-2009 10:42 AM

I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we

Insane World wrote DDD: Living In The Enterprise
on 02-21-2009 10:42 AM

No, not that Enterprise! The other Enterprise – the big amorphous one that organisation spent a fortune

DDD Step By Step wrote DDD: Services
on 02-22-2009 3:35 PM

There can be no word more common in development, and no word used for such a multitude of different things

DDD Step By Step wrote DDD: What Kind of Applications Is It Suited To?
on 02-22-2009 3:36 PM

In many conversations, and in many comments here, you hear phrases like “well that’s not really suited

DDD Step By Step wrote DDD: The Repository Pattern
on 02-22-2009 3:36 PM

I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we

DDD Step By Step wrote DDD: Living In The Enterprise
on 02-22-2009 3:37 PM

No, not that Enterprise! The other Enterprise – the big amorphous one that organisation spent a fortune

#.think.in wrote #.think.in infoDose #18 (26th Jan - 20th Feb)
on 02-23-2009 12:46 AM

#.think.in infoDose #18 (26th Jan - 20th Feb)

Insane World wrote DDD: Living In The Enterprise
on 02-26-2009 4:08 PM

No, not that Enterprise! The other Enterprise – the big amorphous one that organisation spent a fortune

Insane World wrote DDD: The Repository Pattern
on 02-26-2009 4:08 PM

I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we

IHateSpaghetti {code} wrote Blog Carnival #14
on 03-01-2009 1:08 PM

Software architecture Evolutionary Design and Acyclic componentization by Patrick Smacchia Carnival of

Marcus Hammarberg wrote Sprint Planner Helper
on 03-05-2009 12:19 PM

Sprint Planner Helper

Will wrote re: DDD: Aggregates and Aggregate Roots
on 07-14-2009 11:07 AM

ORM and Aggregate separation

If I am using DDD for a Customer / Order type application I would have say a Repository for my Customer Aggregate and a Repository for my Order Aggregate. The Customer Aggregate would of course contain references to Orders.

By using an orm such as NHibernate and mapping a one-to many association,  I could create and access the whole Customer object graph with one call to the database through my Customer Repository. I would then be able to perform CRUD operations on Orders related objects without needing to use an Orders Repository. Should I leave such an association out of my mapping and instead let the Customer Repository create the Order Repository, thus confining operations on Orders to its Repository? This sounds right in DDD terms but one thing I can think of is that I would then lose out on the ORM's ability to handle lazy loading of Orders. Any guidance on this?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)