584

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?

Dinah
  • 52,922
  • 30
  • 133
  • 149
  • 37
    Consider reviewing the following case studies. Effective Aggregate Design Part I: Modeling a Single Aggregate http://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_1.pdf Part II: Making Aggregates Work Together http://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_2.pdf Part III: Gaining Insight Through Discovery http://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_3.pdf – Ben Vitale Feb 09 '12 at 20:50

11 Answers11

407

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.

Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
  • 25
    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)? – Ahmad Mar 08 '10 at 19:40
  • 25
    @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'). – Jeff Sternal Mar 08 '10 at 19:57
  • 5
    Take a look at this eg http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/02/23/strengthening-your-domain-aggregate-construction.aspx . 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? – Ahmad Mar 08 '10 at 20:04
  • 4
    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()). – Jeff Sternal Mar 08 '10 at 20:56
  • 3
    @Jeff You said "they just can't change them" - is that enforceable, or a matter of convention? – Neil Barnwell Feb 03 '11 at 23:52
  • 4
    @Neil: I'd enforce it using whatever language mechanisms are available - for instance, by creating an immutable class to represent the data. – Jeff Sternal Feb 04 '11 at 14:02
  • 2
    @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. – Neil Barnwell Feb 06 '11 at 01:21
  • 3
    @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](http://www.markhneedham.com/blog/2009/03/07/ddd-bounded-contexts/). – Jeff Sternal Feb 06 '11 at 15:44
  • 2
    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 below – Sebastian Good Aug 23 '11 at 00:58
  • 2
    @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). – André Caron Feb 09 '12 at 20:57
  • 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. – Doc Brown Nov 07 '17 at 16:17
271

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.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 69
    [Update from Eric Evans](http://gojko.net/2009/03/12/qcon-london-2009-eric-evans-what-ive-learned-about-ddd-since-the-book/): emphasize that aggregate roots are consistency boundaries for transactions/concurrency and deemphasize that outside entities cannot hold references to other aggregate's child entities. – Brian Low Feb 12 '11 at 04:20
  • 6
    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? – Sinaesthetic Oct 11 '15 at 07:32
  • 1
    Just to get my language right, is the `Customer` class considered the aggregate root, or `Customer` *instances*? – Joe Nov 17 '16 at 16:21
  • 2
    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. – Ibrahim Malluf Dec 05 '16 at 03:51
  • add a note that address could have a different meaning on different domain models and address can't be always a customer BC. – Alireza Rahmani Khalili Jun 23 '20 at 16:19
  • This example with customer and address can be modeled as domain service too – Игор Ташевски Aug 11 '23 at 03:06
184

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.

Marcin Szymczak
  • 11,199
  • 5
  • 55
  • 63
  • 29
    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? – emragins Oct 29 '15 at 04:02
  • 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. – Parama Dharmika Oct 15 '16 at 19:45
  • 4
    @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. – Marcin Szymczak Oct 16 '16 at 22:21
  • 1
    @MarcinSzymczak correct, couldn't agree more that solution is depend on the domain model itself – Parama Dharmika Oct 18 '16 at 09:34
  • 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. – Ibrahim Malluf Dec 05 '16 at 04:04
  • 1
    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? – Mardoxx Dec 09 '17 at 16:56
  • @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. – Marcin Szymczak Dec 09 '17 at 20:59
  • @Marcin totally missed the bit under option B. Lot less confused with myself now! Thanks :) – Mardoxx Dec 10 '17 at 10:02
  • @emragins 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 aggregates – Phillip Copley Jul 02 '18 at 14:17
  • @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? – mko Jul 09 '18 at 11:17
  • @mko 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? – Phillip Copley Jul 19 '18 at 12:48
  • @PhillipCopley does this imply "duplication" of data? – mko Jul 20 '18 at 07:12
  • @mko 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) – Phillip Copley Jul 27 '18 at 13:28
  • Perhaps a better model for it would be Car.Maintenance.ChangeOil() as the action to change oil is usually tied to a maintenance, then you could add Car.Maintenance.Tuneup(), Car.Maintenance.ReplaceTires(), Car.Maintenance.ChangeCoolant() etc. – Mike Sep 18 '19 at 15:19
  • 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`)? – Ama Nov 22 '21 at 11:19
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.

Dinah
  • 52,922
  • 30
  • 133
  • 149
Francisco Aquino
  • 9,097
  • 1
  • 31
  • 37
  • 13
    `where T : IAggregateRoot` - This one made my day – Cristian E. Apr 14 '15 at 17:08
  • 2
    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? – Sinaesthetic Mar 18 '16 at 02:11
  • 2
    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). – Captain Kenpachi Jan 07 '20 at 13:52
  • 2
    The IAggregateRoot technique shows up in Microsoft's documentation: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design – Samuel Danielson Apr 16 '20 at 22:26
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

palash140
  • 673
  • 6
  • 13
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.

Captain Kenpachi
  • 6,960
  • 7
  • 47
  • 68
  • 14
    If you follow a database-first approach then you are not practicing Domain Driven Design, you are following Data Driven Design. – Sinaesthetic Dec 27 '17 at 18:00
  • 10
    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. – Sinaesthetic Dec 28 '17 at 21:27
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

Ibrahim Malluf
  • 657
  • 4
  • 6
  • 1
    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 yet – JorgeeFG May 16 '17 at 14:40
  • 3
    @JorgeeFG the real answer is no one has any sort of clue at all. There is so much conflicting info dotted around. – Mardoxx Dec 09 '17 at 16:51
  • 7
    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. – Sinaesthetic Dec 27 '17 at 17:56
  • @JorgeeFG 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... – jokab Jul 24 '19 at 01:25
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.

ndequeker
  • 7,932
  • 7
  • 61
  • 93
Otávio Décio
  • 73,752
  • 17
  • 161
  • 228
  • 4
    Thank you. That is definitely the most common and frustrating broken link I continually ran across. – Dinah Dec 24 '09 at 15:14
  • 1
    Also, the wording seems backwards. How can the root be *within* the aggreate and be it's parent at the same time? – Sinaesthetic Oct 11 '15 at 07:34
  • 1
    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. – Ibrahim Malluf Dec 05 '16 at 04:11
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.

Alireza Rahmani Khalili
  • 2,727
  • 2
  • 32
  • 33
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.

Marian Venin
  • 111
  • 1
  • 5
  • 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? – Paul-Sebastian Manole Apr 12 '21 at 09:51
-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

Henry H.
  • 901
  • 8
  • 11