What's an Aggregate Root?
Asked Answered
E

11

601

I'm trying to get my head around how to properly use the repository pattern. The central concept of an Aggregate Root keeps coming up. When searching both the web and Stack Overflow for help with what an aggregate root is, I keep finding discussions about them and dead links to pages that are supposed to contain base definitions.

In the context of the repository pattern, what is an aggregate root?

Evered answered 24/12, 2009 at 15:2 Comment(1)
Consider reviewing the following case studies. Effective Aggregate Design Part I: Modeling a Single Aggregate dddcommunity.org/wp-content/uploads/files/pdf_articles/… Part II: Making Aggregates Work Together dddcommunity.org/wp-content/uploads/files/pdf_articles/… Part III: Gaining Insight Through Discovery dddcommunity.org/wp-content/uploads/files/pdf_articles/…Linettelineup
L
422

In the context of the repository pattern, aggregate roots are the only objects your client code loads from the repository.

The repository encapsulates access to child objects - from a caller's perspective it automatically loads them, either at the same time the root is loaded or when they're actually needed (as with lazy loading).

For example, you might have an Order object which encapsulates operations on multiple LineItem objects. Your client code would never load the LineItem objects directly, just the Order that contains them, which would be the aggregate root for that part of your domain.

Leland answered 24/12, 2009 at 15:33 Comment(11)
Hypothetically, if the client code needed the LineItem for some other purpose, would that form a seperate aggregate (assuming there would be other objects involved not related to the Order object)?Columbus
@Ahmad, other aggregates might refer to LineItems as read-only data, they just can't change them. If other aggregates could change them, you couldn't protect the order's invariants (nor the line items').Leland
Take a look at this eg lostechies.com/blogs/jimmy_bogard/archive/2010/02/23/… . In the example, Customer is an invariant of Order, right? However, Customer can also be the another aggregate root? Or am I missing some fundamental understanding here?Columbus
In that example, Customer and Order might both be aggregate roots, but I don't think the author is suggesting you can change Orders via the Customer object (via some method like Customer.RemoveFirstItemFromOpenOrders()) or the reverse (e.g., Order.UpdateCustomerBillingAddress()).Leland
@Jeff You said "they just can't change them" - is that enforceable, or a matter of convention?Eloquent
@Neil: I'd enforce it using whatever language mechanisms are available - for instance, by creating an immutable class to represent the data.Leland
@Jeff what I mean is - how do you create a class that can be part of an aggregate (and therefore modified by other classes in the aggregate) but not modified by classes in a different aggregate? If it's immutable, you can't change it from anywhere.Eloquent
@Neil, I don't know of any languages that make that easy. It's much easier just to create another class to represent that data in contexts where it should be read-only. These are sometimes referred to as bounded contexts.Leland
This answer is right in the context of the repository pattern, but the definition from classic DDD is a little more comprehensive; see @Jason's answer belowIndependence
@NeilBarnwell, @JeffSternal: one way to have a mutable and immutable version of the "same" object is to have a read-only interface (base class with read-only methods) and a mutable concrete type (derived class that has both the read capacity and the write capacity). Some languages make this simpler by offering native support for distinguishing between the two (e.g. the C++ compiler enforces that only const methods are called on const objects).Biweekly
This answer misses the simple fact that there are domain objects which are no aggregates at all. AFAIK these are not called aggregate roots in DDD, but still can be loaded directly from a repo.Shrink
K
276

From Evans DDD:

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE.

And:

The root is the only member of the AGGREGATE that outside objects are allowed to hold references to[.]

This means that aggregate roots are the only objects that can be loaded from a repository.

An example is a model containing a Customer entity and an Address entity. We would never access an Address entity directly from the model as it does not make sense without the context of an associated Customer. So we could say that Customer and Address together form an aggregate and that Customer is an aggregate root.

Kayekayla answered 24/12, 2009 at 15:44 Comment(6)
Update from Eric Evans: emphasize that aggregate roots are consistency boundaries for transactions/concurrency and deemphasize that outside entities cannot hold references to other aggregate's child entities.Deguzman
So the verbiage is forever confusing me. Each AGGREGATE has a root and The root is the only *member* of the AGGREGATE -- this verbage implies that the root is property on the Aggregate. But in all of the examples, it's the other way around: the root contains properties that are aggregates. Can you clarify?Important
Just to get my language right, is the Customer class considered the aggregate root, or Customer instances?Hackbut
Generally speaking in the Customer-order-line-item paradigm the Customer would be the Aggregate Root. The Instance of a customer would be an instance of that Aggregate Root. When speaking of an Aggregate Root called Customer you are discussing the logical construction of a Customer that makes up the instance of a customer. A collection of Customers is just a collection.Havelock
add a note that address could have a different meaning on different domain models and address can't be always a customer BC.Calcium
This example with customer and address can be modeled as domain service tooCalva
R
190

The aggregate root is a complex name for a simple idea.


General idea

Well designed class diagram encapsulates its internals. Point through which you access this structure is called aggregate root.

enter image description here

Internals of your solution may be very complicated, but users of this hierarchy will just use root.doSomethingWhichHasBusinessMeaning().


Example

Check this simple class hierarchy enter image description here

How do you want to ride your car? Chose better API

Option A (it just somehow works):

car.ride();

Option B (user has access to class inernals):

if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
    for (Wheel w: car:getWheels()){
        w.spin();
    }
}

If you think that option A is better then congratulations. You get the main reason behind aggregate root.


Aggregate root encapsulates multiple classes. you can manipulate the whole hierarchy only through the main object.

Rooky answered 25/9, 2015 at 12:34 Comment(14)
I like the example, but I'm struggling to find a scenario in which Customer should reference Engine. It seems like Engine should be encapsulated behind Car. Can you elaborate on this a little?Thor
In my opinion the engine itself must be inside a car specific model, e.g a BMW series 5 with 3000cc engine. With this modeling the engine is a component for a car.Anastasiaanastasie
@ParamaDharmika sure, you can model it that way. That depends on how 'advanced' with cars is your customers. In basic model he should have access to car aggregate root. You can also allow situation like one on the drawing. Correct solution depend on business model of application. It might be different in each case.Rooky
@MarcinSzymczak correct, couldn't agree more that solution is depend on the domain model itselfAnastasiaanastasie
Actually, the Wheel is an aggregate that contains Tire (and other parts). If your rules require that the Wheel aggregate can only be accessed through the Car Root-Aggregate, then the engine is also contained within the Car Root Aggregate and should not be accessed outside of the Car. That's in the realm of a Car instance. A car owner (Customer) would not reference an engine except in the context of his/her car.Havelock
So now your car object is responsible for returning objects? Your car is now a repository - of sorts e.g. car.GetTyres()? How is this good?Gadfly
@Mard Car does not return tires at all. User of car should not have this method. He should only have method .ride(). Underneath it will do something with tires. But car user does not have to know how it happens.Rooky
@Marcin totally missed the bit under option B. Lot less confused with myself now! Thanks :)Gadfly
@Thor engine.AddOil() would be an example. You could model it as car.AddOil() sure, but if you have multiple car-independent engine operations, or you're modeling a service/repair center, it may make sense to model the engine and the car as distinct aggregatesPeen
@PhillipCopley but if you want to check the oil before starting a car, how would you check the car.checkOilLevel() if a an engine is a separate aggregate, outside the car aggregate?Trexler
@Trexler engine.checkOilLevel() if you're checking the engine directly, or perhaps car.checkOilGauge() if you're checking it from within the car via the instrument panel?Peen
@PhillipCopley does this imply "duplication" of data?Trexler
@Trexler It might depending on how you implement it but I don't think so necessarily. I think it's just modeling the use case that there are multiple ways to check the same information (and perhaps car.checkOilGauge() is merely a projection)Peen
I am in a similar situation where projects (aggregate) have several project, which have one template (aggregate of value objects) and one charts (aggregate), which have several chart, which have several shape (value object). Should only projects be defined as an aggregate root, or is it acceptable to have charts being another aggregate root as well (albeit referenced by projects)?Ankle
U
47

Imagine you have a Computer entity, this entity also cannot live without its Software entity and Hardware entity. These form the Computer aggregate, the mini-ecosystem for the Computer portion of the domain.

Aggregate Root is the mothership entity inside the aggregate (in our case Computer), it is a common practice to have your repository only work with the entities that are Aggregate Roots, and this entity is responsible for initializing the other entities.

Consider Aggregate Root as an Entry-Point to an Aggregate.

In C# code:

public class Computer : IEntity, IAggregateRoot
{
    public Hardware Hardware { get; set; }
    public Software Software { get; set; }
}

public class Hardware : IEntity { }
public class Software : IValueObject { }

public class Repository<T> : IRepository<T> where T : IAggregateRoot {}

Keep in mind that Hardware would likely be a ValueObject too (do not have identity on its own), consider it as an example only.

Unguiculate answered 24/12, 2009 at 15:15 Comment(4)
where T : IAggregateRoot - This one made my dayMarko
The wording is a little contradictory, I think and this is what confuses me when trying to learn this. You're saying that the Computer is the aggregate, but then you're saying that the root would be the mothership entity INSIDE the aggregate. So which one is the "mothership" entity inside the aggregate in this example?Important
Greetings from the future!. What the guy means is that the Computer by itself is the aggregate root, while the computer AND everything inside it is the aggregate. Or more clearly: the case by itself is the aggregate root, while the whole computer is the aggregate (the collection of everything that makes up the "computer, e.g. RGB lighting, Hardware, Power Supply, OS, etc).Hanako
The IAggregateRoot technique shows up in Microsoft's documentation: learn.microsoft.com/en-us/dotnet/architecture/microservices/…Match
S
20

Aggregate means collection of something.
root is like top node of tree, from where we can access everything like <html> node in web page document.
Blog Analogy, A user can have many posts and each post can have many comments. so if we fetch any user then it can act as root to access all the related posts and further comments of those posts. These are all together said to be collection or Aggregated

Sabbat answered 16/8, 2016 at 20:24 Comment(1)
This is a good explanation without confusing terminologyVevay
H
18

If you follow a database-first approach, you aggregate root is usually the table on the 1 side of a 1-many relationship.

The most common example being a Person. Each person has many addresses, one or more pay slips, invoices, CRM entries, etc. It's not always the case, but 9/10 times it is.

We're currently working on an e-commerce platform, and we basically have two aggregate roots:

  1. Customers
  2. Sellers

Customers supply contact info, we assign transactions to them, transactions get line items, etc.

Sellers sell products, have contact people, about us pages, special offers, etc.

These are taken care of by the Customer and Seller repository respectively.

Hanako answered 10/9, 2013 at 8:15 Comment(2)
If you follow a database-first approach then you are not practicing Domain Driven Design, you are following Data Driven Design.Important
It's a Q&A forum where people come to solve problems and/or learn -- That wasn't me poking at you. By definition, DDD is a mindset more than anything else and it is confusing for many, so this was me making sure the comment was made for those that are learning DDD in effort to help mitigate any potential conflation of design methodologies.Important
H
17

Dinah:

In the Context of a Repository the Aggregate Root is an Entity with no parent Entity. It contains zero, One or Many Child Entities whose existence is dependent upon the Parent for it's identity. That's a One To Many relationship in a Repository. Those Child Entities are plain Aggregates.

enter image description here

Havelock answered 5/12, 2016 at 4:45 Comment(4)
So, if you are a car seller, then Car would be an aggregate root on its own right? Because you can have many cars that don't have a customer yetKean
@Kean the real answer is no one has any sort of clue at all. There is so much conflicting info dotted around.Gadfly
Child entities are not aggregates, they are just entities that happen to be members of the aggregate in which the aggregate root controls. An "aggregate" is a logical grouping of entities.Important
@Kean it really depends on the bounded context you are designing. If you are a car seller, then something like a Carshop becomes the aggregate root, and below it follows the Cars...Boeotian
M
15

From DDD Step By Step (offline):

Within an Aggregate there is an Aggregate Root. The Aggregate Root is the parent Entity to all other Entities and Value Objects within the Aggregate.

A Repository operates upon an Aggregate Root.

More info can also be found here.

Manara answered 24/12, 2009 at 15:12 Comment(3)
Thank you. That is definitely the most common and frustrating broken link I continually ran across.Evered
Also, the wording seems backwards. How can the root be within the aggreate and be it's parent at the same time?Important
The Aggregate Root is the root class. A plain Aggregate is always contained within an Aggregate Root. Using the Diagram posed above...The Customer is the Aggregate-Root. The Customer can own one or more cars. Cars are Aggregates in relation to the Customer. Cars have an Engine. The Engine is an Aggregate contained in the Car Aggregate. What makes the Customer an Aggregate Root is the model's assumption that access to a car or it's components are always through the customer who owns the car.Havelock
C
3

Aggregate is where you protect your invariants and force consistency by limiting its access thought aggregate root. Do not forget, aggregate should design upon your project business rules and invariants, not database relationship. you should not inject any repository and no queries are not allowed.

Calcium answered 16/9, 2017 at 9:2 Comment(0)
W
0

In another world, in Event Sourcing, an Aggregate(Root) is a different concept. Event Sourcing might be encountered together with CQRS, DDD etc.

In Event Sourcing an Aggregate is an object for which the state (fields) is not mapped to a record in a database as we are used to think in SQL/JPA world.

Is not a group of related entities.

It is a group of related records like in a history table.

GiftCard.amount is one field in a GiftCard Aggregate, but this field is mapped to all the events, like card-redeemed (take money from the card) ever created.

So the source of data for your Aggregate is not a record in a database but the complete list of events ever created for that specific aggregate. We say we event sourced the aggregate.

Now we can ask ourselves how is it done? Who is aggregating these events so we are operating still with one field e.g GiftCard.amount? We might be expecting that amount to be a Collection and not a big-decimal type.

Is the event sourcing engine, doing the work, who might simply replay all the events in the creation order. But this is out of the scope for this thread.

Wheezy answered 26/6, 2020 at 10:58 Comment(1)
Seems like a whole lot of work to do each time you access a field. And the work grows exponentially with time. Any tricks being applied? Snapshots maybe?Linear
S
-3

In Erlang there is no need to differentiate between aggregates, once the aggregate is composed by data structures inside the state, instead of OO composition. See an example: https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-london

Sideward answered 9/3, 2016 at 12:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.