Home » Code » What are Aggregates in Domain Driven Design?

What are Aggregates in Domain Driven Design?

Posted by on December 17th, 2014

What are Aggregates in Domain Driven Design
As an application begins to grow in complexity, the web of interconnected Entities and associations can begin to get overwhelming. What was once a simple set of Entities and relationships is suddenly a sprawling mess of objects and associations.

When the number of interconnected objects increases, so too does the surface area for interacting with those objects. Certain objects will have child objects, and those objects will have further related objects.

Domain Driven Design is all about allowing the model to drive the direction of development. When the complexity of the object graph inevitably becomes overwhelming, it’s time to take a closer look at the model to understand how to resolve the issues.

Aggregates are a way to calm this complexity by reducing the web of connected objects into a single unit. In today’s article we’re going to be looking at Aggregates, how they work and why you would want to use them in a Domain Driven Design project.

The problem of complexity

When code becomes too complex, bugs can creep in through ambiguity.

In a simple application, all objects will have equal precedence within the application. For example, if we were creating a forum application, we would probably have Thread, Post and Reply objects. Each Thread would have child Post objects and certain Post objects would have Reply objects.

When all objects have equal precedence, we could very easily select any of these objects straight from the database using their unique id:

$reply = Reply::find(4526);

However, what about the rules of our application? If only certain users can post in a Thread how do we prevent them from adding a Reply object to a Post? What about when a Thread is deleted? How do we deal with all of the child Post objects and their Reply objects?

Looking to the model for answers

In any non-trivial application, there is likely going to be a lot of rules around how the objects should interact and coexist together. In reality, these objects should not have equal precedence in the application.

A Post object only really make sense in the context of a Thread because we can’t have a Post without a Thread, and we definitely can’t have a Reply without a Post.

When all objects have equal precedence we have created a massive interface for interacting with those objects. However, when we actually take a closer look at the model we are building, it does not make sense for those objects to be globally accessible. If an object shouldn’t appear outside of the context of it’s parent, we have no business having access to it in isolation.

Aggregates are the answer

An Aggregate is a cluster of associated object that we treat as a single unit. Each Aggregate has a single root Entity and a boundary that marks what is inside and what is outside of the Aggregate.

The root Entity is the only Entity that is globally accessible in the application. In the example from above, Thread would be the root Entity.

Inside the boundary we would have all of the associated objects of this Aggregate. For example, we would have the Post and Reply Entities as well as any other Entities or Value Objects that make up the Aggregate.

The Post and Reply objects can hold references to each other internally to the Aggregate, but no other external object can hold a reference to any object internally to the Aggregate that is not the root Entity.

The only way to access the Post and Reply Entities is to retrieve the Thread root Entity and traverse it’s associated objects.

The benefits of using Aggregates

To fully appreciate why you would want to structure your application around Aggregates, I think its important to first understand the benefits of using them. Without understanding the benefits, Aggregates can seem a bit like a needless artificial constraint in your code.

I think there are basically 3 benefits to using Aggregates.

A simple interface

The first big benefit of Aggregates is that it greatly reduces the interface you have to a certain segment of your application.

Imagine it’s your first day on the job of our imaginary forum development project and you’ve been tasked with making a change to some existing functionality.

Having unrestricted power to manipulate any object in the application is only going to lead to bad things happening. Without the constraints of an Aggregate a developer without the understanding of the business rules of the application will likely break those rules or expose an object that should not be exposed.

By having a single point of entry to the Aggregate, we can constrain access to the internal objects and maintain the harmony inside of the boundary. Having a single point of entry also makes it much easier to work with the code for the first time because there is no ambiguity of how you are supposed to access the child objects of a parent object.

Maintaining the invariants

The real beauty of Domain Driven applications is the ability to model the business rules of the application through invariants. An invariant is a rule that must remain consistent.

For example, if there was a business rule that stated only users who had posted in a thread could reply to other posts, we would be able to maintain this rule through the constraint of the Aggregate.

Maintaining the invariants of a unit of objects would be difficult without the constraint of the Aggregate boundary. If we didn’t have the boundary it would be very easy to simply create a new Reply and associate it with a Post.

Instead, the Thread can be in charge of deciding whether a Reply is valid or not, and so any attempt to circumvent this rule would be stopped.

Removing Objects

A common problem when building web applications is how to safely remove objects. When we don’t have constraints around what objects can be associated with other objects, this can start to become scary.

For example, if we didn’t restrict the associations of the application and we wanted to delete a Thread, how could we be certain that we wouldn’t be breaking other associations by cascading through the relationships of the Thread?

If we were to delete just the Thread we would be leaving lots of Post and Reply garbage objects in the database that no longer had context within the application.

Using Aggregates removes this problem because all objects within the boundary of the Aggregate are forbidden from being associated with any object outside of the boundary. This means we can delete the Thread and all of it’s internal associated objects without being scared of breaking associations across the application.

Conclusion

Thinking about your application as a set of main Aggregates can really clarify your thought process when designing what you need to build. Aggregates attract responsibility and capture a lot of the nuances of an association between two objects so it is not lost in complexity.

Now of course, there will always be ways to circumvent the constraints that an Aggregate puts in place. But I think the process of identifying and modelling your application in terms of Aggregates can really help distill the problem you are trying to tackle.

Using Aggregates also makes it a lot easier to make certain decisions. For example, it can be difficult to decide who has responsibility for creating and maintaining the relationship between Entities. When you identify and implement Aggregates you don’t have to ponder this decision because the model should have already guided you to the right answer.

So even if your next project isn’t a fully blown Domain Driven Design application, I would encourage you to start thinking about your code in terms of Aggregates and where the lines of responsibility between objects fall.

Philip Brown

Hey, I'm Philip Brown, a designer and developer from Durham, England. I create websites and web based applications from the ground up. In 2011 I founded a company called Yellow Flag. If you want to find out more about me, you can follow me on Twitter or Google Plus.

  • pixelBender67

    Love your articles mate

  • Juukie14

    Very clear explained :)

  • Matt

    Interesting stuff and very well explained. I wonder: how big can or may aggregates become? Thinking about a model where you have a very hierarchical relationship between the things. Say you have an application for tracking Visits to certain Places. Places are locations in Sectors. Sectors are located in Areas. Areas are locations in Countries. Now what would be the Aggregate? A country? An area? A sector? Maybe a country is too big, because getting the country (from the db, eventually) to get access to all Visits, might mean getting many tens of thousands of them in one time. Maybe area is better? Sector too small? :)

    • Thank you :)

      I would look to the business for the answer. Often when there seems like there is an unclear decision its simply because you don’t quite understand how the business thinks about the problem in question.

      • Matt

        So what you mean is: what is more important? Like if Areas are a more important aspect of the whole model compared to sectors, you would take areas as the aggregate. Countries would probably be too generic (the business is not about countries itself).

        Great series of articles!

        • Yeah exactly! Try and find what the business values and where it naturally places emphasis and let that guide your decision making. Yeah I’d imagine Countries is too big, but if you were struggling to decide between Areas and Sectors, I would look deeper into the business to truly understand the intricacies.

          Thank you :)

  • Pingback: What are Factories in Domain Driven Design? | Culttt()

  • Pingback: Enforcing Business Rules through Aggregate Instantiation | Culttt()

  • Pingback: Using Aggregates as a Gateway to Functionality | Culttt()

  • Ahesanali Suthar

    Hi Philip,

    Nice post and found very interesting information in object oriented direction.

    But i have one question for below sentences:

    “If we were to delete just the Thread we would be leaving lots of Post andReply garbage objects in the database that no longer had context within the application.”

    Can above functionality not be achieved by database relationship?

    I mean if i design database relationship in such a way that it will delete it’s dependent records when it’s parent got deleted.

    • Thank you :)

      Yes that is absolutely correct. However, I tend to not use database relationships.