DDD – The aggregate

In my last posts I revisited domain driven design (DDD), applied it to a concrete domain and shed some light onto special scenarios (here and here) and how one could possibly solve them using DDD. In this post I want to talk a little bit more about the aggregate and how I like to implement it.

The aggregate is a logical boundary for things that can change in a business transaction of a given context. An aggregate can be represented by a single class or by a multitude of classes. If more than one class constitutes to an aggregate then one of them is the so called root class or entity. All access to the aggregate from outside has to happen through the root class. The outside world should only ever see (an interface to) the root class. Everything else remains internal to the aggregate.

As a consequence only the root class or entity needs a globally (!) unique ID. Any other entity only requires a locally unique ID (that is an ID that is unique inside the boundaries of a given aggregate instance).

Implementing an aggregate

Let’s make a simple sample. Imagine we have a loan application aggregate. To distinguish my aggregates from other objects I personally like to suffix their names with -Aggregate. Thus we have a LoanApplicationAggregate. To start with and to keep it simple this aggregate consists of a single class

public class LoanApplicationAggregate
{
	// implementation details go here
}

It is important to notice that the aggregate is a POCO and thus doesn’t inherit from or depend on some framework (base class).

To avoid that implementation details of the aggregate leak out and to enforce the tell don’t ask principle I tend to keep the state of the aggregate private to the aggregate. The state of the aggregate is usually represented by properties. For our loan application aggregate some typical attributes or properties of the state are:

  • email, address, social security number, annual income (of the borrower),
  • requested loan amount, bank account, etc.

we can implement those as follows

public class LoanApplicationAggregate
{
	private string _email;
	private string _ssn;
	private string _streetAddress;
	private string _city;
	private string _zip;
	//...
	// more implementation details go here
}

There is one exception though to this. I want to make the globally unique ID of the aggregate public but read only. Thus I have

public class LoanApplicationAggregate
{
	public Guid Id { get; private set; }
	//...
	// more implementation details go here
}

In general working with GUIDs instead of e.g. integers as IDs that need to be globally unique has proven to be very straight forward, robust and scalable. GUIDs can be generated anywhere without the danger of collisions. That’s the reason I have chosen our ID to be of type GUID.

Now when doing DDD then the aggregates are the place where interesting stuff happens. Here you are going to implement most of the application or domain specific business logic. Thus aggregates are much much more than pure data containers or DTOs.

Ideally the aggregate exposes an interface to the outside world with intention revealing method names that can be called. In our situation such an intention revealing method could be StartApplication and another one could be SubmitApplication. This could look somewhat like

public class LoanApplicationAggregate
{
	public Guid Id { get; private set; }
	//...
	public void StartApplication(Guid id, string email, string firstName, string lastName)
	{
		//details omitted
	}
	
	public void SubmitApplication()
	{
		//details omitted
	}
	// more implementation details go here
}

Note how the former method has four parameters id, email, firstName and lastName whilst the latter doesn’t need a parameter. This means that we can only start an application if we provide (at least) a unique ID, the email address and first and last names of the borrower. On the other hand telling the aggregate that it is to be submitted needs no other data.

A method body usually consist of some code that checks the preconditions and makes sure that the execution of this method does not violate some business constraints. What could that mean? In the case of starting a new application a precondition check could be that one cannot start the same application more than once. In the case of submitting an application a typical precondition check could be to verify that only an application that is currently in status Draft can be submitted. The implementation could then look like this

public class LoanApplicationAggregate
{
	public Guid Id { get; private set; }
	private LoanApplicationStatus _status;
	//...
	public void StartApplication(Guid id, string email, string firstName, string lastName)
	{
		if(Id != Guid.Empty)
			throw new InvalidOperationException("Cannot start an already started application");
			
		//further details omitted
	}
	
	public void SubmitApplication()
	{
		if(_status != LoanApplicationStatus.Draft)
			throw new InvalidOperationException("Can only submit a draft application")
			
		//further details omitted
	}
	// more implementation details go here
}

Another important part of the method body is to update the internal state. Thus we have

public class LoanApplicationAggregate
{
	public Guid Id { get; private set; }
	private LoanApplicationStatus _status;
	//...
	public void StartApplication(Guid id, string email, string firstName, string lastName)
	{
		if(Id != Guid.Empty)
			throw new InvalidOperationException("Cannot start an already started application");
		
		Id = id;
		_email = email;
		_firstName = firstName;
		_lastName = lastName;
		_status = LoanApplicationStatus.Draft;
		//further details omitted
	}
	
	public void SubmitApplication()
	{
		if(_status != LoanApplicationStatus.Draft)
			throw new InvalidOperationException("Can only submit a draft application")
			
		_status = LoanApplicationStatus.Submitted;
		//further details omitted
	}
	// more implementation details go here
}

Note how in the StartApplication method we automatically set the status of the aggregate to Draft whilst in the SubmitApplication method we set the status to Submitted.

Finally there could be the need to publish some event to the outside world that something interesting has happened. Interested parties (called observers) could then react to this/these event(s) and do something important on their turn. [In a typical enterprise application such events could be published on a bus, e.g. NServiceBus, Mass Transit or similar - but this is outside of the scope of this post]

public class LoanApplicationAggregate
{
	private List<object> _unpublishedEvents = new List<object>();
	//...
	public void SubmitApplication()
	{
		if(_status != LoanApplicationStatus.Draft)
			throw new InvalidOperationException("Can only submit a draft application")
			
		_status = LoanApplicationStatus.Submitted;
		
		Publish(new LoanApplicationSubmitted{ Id = Id });
		//further details omitted
	}
	
	private void Publish(object @event)
	{
		_unpublishedEvents.Add(@event);
	}
	// more implementation details go here
}

The internal Publish method just adds the passed event to a collection of yet unpublished events. The infrastructure which hosts the aggregate will then be responsible to e.g. dispatch these unpublished events to the bus.

After having shown some implementation details it is time to refactor the whole aggregate a bit. I personally like to separate concerns inside the aggregate. For me the aggregate should be responsible for the business logic and house keeping whilst the state should be maintained by a separate object. I call this new object the State object. In our case I introduce a new class called LoanApplicationState. An instance of this class will be private to each aggregate instance. Here is this state class

public class LoanApplicationState
{
	public Guid Id { get; set; }
	public LoanApplicationStatus Status { get; set; }
	public string Email {get; set; }
	public string FirstName {get; set; }
	public string LastName {get; set; }
	public string StreetAddress {get; set; }
	public string City {get; set; }
	public string Zip {get; set; }
	public string SSN;
	//...
	
}

An here is how I use it inside my aggregate

public class LoanApplicationAggregate
{
	private LoanApplicationState _state;
	//...
	public LoanApplicationAggregate(LoanApplicationState state)
	{
		_state = state;
	}

	public void StartApplication(Guid id, string email, string firstName, string lastName)
	{
		if(Id != Guid.Empty)
			throw new InvalidOperationException("Cannot start an already started application");
		
		_state.Id = id;
		_state.Email = email;
		_state.FirstName = firstName;
		_state.LastName = lastName;
		_state.Status = LoanApplicationStatus.Draft;
		//further details omitted
	}
	
}

As I said this helps me to separate concerns and as an added bonus makes unit tests or TDD much more elegant. Let’s now have a look how we can test such an aggregate

 Testing the aggregate

Given the way we have implemented the aggregate so far and specifically considering the fact that we have separated the state of the aggregate into its own class makes testing really straight forward. When using NUnit as our testing framework then I like to implement a simple base class which allows me to write tests in a Give-When-Then style. Here is this base class together with the definition of a Then attribute

[TestFixture]
public abstract class SpecificationBase
{
	[SetUp]
	public void SetUp()
	{
		Given();
		When();
	}
	
	protected virtual Given() { }
	protected virtual When() { }
}

public class ThenAttribute : TestAttribute { }

Now I can write a simple test for the StartApplication method

public class when_starting_a_new_loan_application : SpecificationBase
{
	private LoanApplicationAggregate sut;
	private LoanApplicationState state;
	private Guid id;
	private string email, first, last
	
	protected override void Given()
	{
		state = new LoanApplicationState();
		sut = new LoanApplicationAggregate(state);
		id = Guid.NewGuid();
		email = "jdoe@foo.com"
		first = "John";
		last = "Doe";
	}
	
	protected override void When()
	{
		sut.StartApplication(id, email, first, last);
	}
	
	[Then]
	public void it_should_set_the_id_of_the_state() 
	{
		Assert.That(state.Id, Is.EqualTo(id));
	}
	
	[Then]
	public void it_should_set_the_status_to_draft() 
	{
		Assert.That(state.Status, Is.EqualTo(LoanApplicationStatus.Draft));
	}
}

Note how I always call the class I am testing the system under test (sut, see line 3 above). Also note how I setup the preconditions in the Given method, I then act in the When method and finally I have a method decorated with the [Then] attribute for each assertion. Also note how I can use the state object in my assertions. This is really cool; I can now access any detail of the state object although during runtime the state is private to the aggregate!

Similarly I can write a unit test for the SubmitApplication method to assert that an exception is thrown if the loan application is not in status Draft.

public class when_submitting_an_already_submitted_application : SpecificationBase
{
	private LoanApplicationAggregate sut;
	private LoanApplicationState state;
	
	protected override void Given()
	{
		state = new LoanApplicationState
		{
			Id = Guid.NewGuid(),
			Status = LoanApplicationStatus.Submitted
		};
		sut = new LoanApplicationAggregate(state);
	}
	
	[Then]
	public void it_should_fail()
	{
		Assert.Throws<InvalidOperationException>(() => sut.SubmitApplication());
	}
}

Since the aggregate is the place where most of the critical and business specific action happens it is also the place for which you would probably want to write most of your unit tests. Using the implementation patterns that I have shown above it is a joy and straight forward to implement unit tests for even the most exotic edge cases.

Persisting the aggregate

Assuming that we are working with a relational database backing our application it makes sense to use the aggregate state object as the object we want to persist since it encapsulates all state. If we are using an ORM like NHibernate or Entity Framework it is straight forward. Let’s assume we are using NHibernate in our application combined with Fluent NHibernate for the mapping of (data-) entities to underlying tables in the database then we just need to make all the properties of our state object virtual. Thus we have

public class LoanApplicationState
{
	public virtual Guid Id { get; set; }
	public virtual LoanApplicationStatus Status { get; set; }
	public virtual string Email {get; set; }
	//...
}

We can then use code similar to this to re-hydrate an aggregate from storage

public LoanApplicationAggregate GetById(Guid id)
{
	var state = _session.Get<LoanApplicationState>(id);
	var aggregate = new LoanApplicationAggregate(state);
	return aggregate;
}

here _session is an object of type ISession. Persisting the changed state of the aggregate is similarly straight forward

public void Save(LoanApplicationAggregate aggregate)
{
	var state = aggregate.GetState();
	_session.Save(state);
}

which of course implies that the aggregate provides a GetState method returning its internal state for persistance.

Note that the whole re-hydration and persisting of aggregates can be further abstracted using the repository pattern that I have introduced in earlier posts (e.g. this one).

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 25 years as a consultant, software architect, trainer, and mentor mainly on the .NET platform. He is currently working as senior software architect at Alien Vault in Austin, Texas. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in architecture, DDD, design, How To, patterns, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1867()

  • Daniel Whittaker

    Thanks Gabriel – another great post! Aggregates and Aggregate Roots seem to be a big point of confusion when starting out.

    I like your approach to testing. It seems very elegant and easy to do. I’ve played around with some other approaches using similar base classes. Aggregates lend themselves to good tests and is one the great strengths of the DDD approach.

    If it’s helpful I’ve written a post about building Aggregates in a CQRS context (rather than a ORM and relational DB). You can find it here:

    http://danielwhittaker.me/2014/11/15/aggregate-root-cqrs-event-sourcing/

    Anyway – Thanks for this great series! Keep them coming.

    • armando sard

      Great article. Is it safe to say aggregates are in fact services? as it has behavior only

  • Thanks for sharing.
    I think all your code example got lost.

    • gabrielschenker

      The code samples are there but sometimes the browser doesn’t display them correctly. Often refreshing the browser helps… Sorry for that

      • jbogard

        Perhaps we need instructions at the top, “JUST HIT F5″

        • gabrielschenker

          LOL

  • Miguel A. Gonzalez

    Great stuff Gabriel!

  • MB

    Nitpick: The Aggregate in LoanApplicationAggregate is a suffix, not a prefix

    • gabrielschenker

      fixed. Thanks for reporting it.

  • The implementation examples are pretty solid, but I would refer at least to Vaugh Vernon’s three articles on Effective Aggregate Design. They are crucial to understand how to model your aggregates. Most people make the mistake of using the composition aspects as a guide rather than the consistency boundaries.

  • Ricardo da Silva

    Thank you for this great post. in particular the use of passing state into the Aggregate as a ‘dto’. I have been trying figure a best approach when dealing with aggregates having polymorphic child entities. Although I am not sure that my implementation is entirely correct. I have posted this question , “Domain Driven Design and Working with Polymorphic Child Entities”, on several forums but, to date, no one seems to be providing any further insight on critique. I would be very grateful if you you could possible have a look at it and provide some pointers please.

    http://stackoverflow.com/questions/30400317/domain-driven-design-and-working-with-polymorphic-child-entities

  • Ross

    Tried out the testing approach used–that really is a breath of fresh air! Thanks for including that in the post.

  • Pingback: From my reading list #27 – July 6th, 2015 | Pascal Laurin()

  • Tom Eugelink

    Is it me, or am I the only one seeing an anemic model in this?

    The DTO is made public through the agregate’s public constructor. And it has an id. So we have an object with an id, and that is persisted… Sounds like an entity in a anemic model to me.

    Given this, where does the business logic in an anemic model go? Well, in stateful or stateless session beans, instantiated to manipulate the entity. That basically is what the aggregate does? Like a stateful session bean?

    • gabrielschenker

      It is not an anemic model. The aggregate contains all the logic and I just separated the state into it’s own class to achieve a separation of concern between business logic and state management.

      • Tom Eugelink

        I understand how you see that. But putting on other glasses, I also see a class with an id that is persisted by a repository, and another class adding business logic to that.

      • armando sard

        so an aggregate can have business logic as well as state management. a service can have business logic but no state management. i guess that is the difference between an aggregate and services

  • Lloyd Dreghorn

    Great post! I really like the idea of separating the state from the behaviour, however it got me thinking…. If we are supposed to use the behaviour of our aggregate to change its state, e.g. ‘loanApplicationAggregate.StartApplication(…,..)’ changes the ‘_state.Status’ to LoanApplicationStatus.Draft. What stops someone from doing this:

    var state = (LoanApplicationState)loanApplicationAggregate.GetState();

    state.Status = LoanApplicationStatus.Submitted;

    This state change will change the state of Status without even calling .StartApplication(…). Now, one could just save this aggregate without using its behaviour and this UNWANTED state will be persisted to the database??

    If we didnt use a LoanApplicationState object, we could just put a private setter on the ‘Status’ property, thus forcing the user of the aggregate to use its behaviour to change its state.

    So my question is: How do we enforce the same when using a state object?? We cant exactly put a private setter on the state object because then we wouldnt be able to change it within our aggregate… I am still new to DDD so i am just trying understand how to achieve encapsulation of the state object??

    • gabrielschenker

      Don’t try to make a system absolutely fool proof just make it such that one cannot hurt oneself accidentally. In the end developers have a brain and can think ;-)

      • Lloyd Dreghorn

        Thanks for clearing that up Gabriel! As I said before, great post! Thanks!

  • Dan Testa

    The SubmitLoanApplication test example above look like it is missing the When() method. Great series of posts! Thanks for demystifying DDD, CQRS, Event Sourcing, etc. I am eager to adopt these practices on my projects where appropriate.

  • Thanks for the post. The notion of aggregate is very hard to grasp. Why do you consider your LoanApplication as an Aggregate and not an Entity ?

    I am asking this because in your definition you state : “The aggregate is a logical boundary for things that can change in a business transaction of a given context”.

    By things I would understand objects. Here from what I see, we are dealing with only one object which is a LoanApplication. This is the kind of question I am alsways asking myself, so I would love your opinion on that.

    Are you suggesting that Entities should be POCOs and Aggregates should contain the business logic ?

    • gabrielschenker

      An aggregate is as stated in the post a logical concept. When we look at the concrete implementation then an aggregate consists of at least one entity. It can be several entities of which one is defined as the root. Take an “Order Aggregate” as a sample. This could designed to consist of an Order Entity (which is the root), a collection of LineItem Entities, etc. The aggregate would have to be always accessed through the root entity. That is in the Order sample no one from outside the aggregate can directly access a LineItem entity.

      • armando sard

        IS AGGREGATES and services same thing. I mean both are use for business rules in domain

        • gabrielschenker

          It can be but it doesn’t have to be. An aggregate is more a logical boundary for what can be affected by a typical business transaction (NOT DB transaction)

  • armando sard

    Is it safe to assume aggregates are services?