Modelling Aggregate Roots Relationships

By Mike on 18 October 2013

 One of the most important things when doing DDD is to model the aggregates, entities, value objects and their relationships the right way. And this is also one of the most trickiest things. In this post I'll try to show you some examples of both superficial and proper domain relationships modelling. But first let me say this loud and clear: Domain relationships have NOTHING to do with and they are totally unrelated to database (persistence) tables relationships. And remember that when modelling the database (any type) doesn't exist.

 Keep in mind that when defining a concept, we care  about what an entity or value object IS. Regarding a HAS relationship, it's important to understand that the 'has' is about a component(child) required by the concept or a component that changes the parent's behaviour. There can be also 'work with' relationships, where two ore more aggregate roots (AR) have a partnership, thus working together to achieve a domain use case.

 But let's start with an all time favourite, Post and Comments.  Everybody knows that a post has comments, so it appears to make sense that the Post AR holds (acts as a container for) Comments. Leaving aside the technical "I need to load 1000 comments in order to add another one", this is an example of superficial domain understanding. A Post doesn't need comments in order to be exist as a Post . The concept of a Post is totally unrelated to the concept of a Comment. A comment is an user submitted message. Wordpress, Youtube and Facebook are using comments and the comment definition is the same, regardless the subject users are commenting on. Considering comments part of a post AR is like considering an advert part of the post AR, just because they're both on the same page and the ad content depends on the post content. But modelling domain is ONLY about the domain concepts and processes; at this point we don't care how some things are shown in a page or how they will be used together outside the domain.

 Consider a table and chairs.  When you go in a restaurant, you'll see tables with at least 1-2 chairs nears them. You can say that a table has 2 chairs. But can you use a table without chairs? Yes. Can you use a chair without a table? Of course! The fact is that the table and chairs are working together in order to provide business value. The table's "has" relationship is not with the chairs, it's with the table leg(s). A table has 4 legs, because without them, it's not really a table, it's just a surface.

 One of the 'real' parent-children relationship is when the AR needs those concepts as part of its definition. A Post has a title (which is a value object), but never has comments. Posts and comments are working together because you want to involve your readers and you're using the post to give them an incentive to comment. If you're putting comments inside a post AR, you're treating the AR just as a container, breaking the Single Responsibility Principle and improperly modelling the domain. It's like saying that a restaurant table needs to hold chairs inside it in order to be and act as a table.

 Let's look a bit at a smartphone. I will focus on 2 components of it: the SIM card and the battery. We can safely say that you can have a phone without a SIM card and a battery. SIM cards and batteries can exist without a phone. However, a phone without SIM card has some restrictions. A phone without a battery has A LOT of restrictions i.e it's useless. A phone can work without a SIM card but it requires one in order to enable all its functionality. Of course, the lack of battery removes all the phone's functionality.

These 2 components change the phone behaviour. A phone HAS a SIM card, because a SIM card is required in order to access the carrier's network. A phone HAS a battery because, it needs a power source. The phone is a great example for an AR. Not only it has a lot of components, but it also acts as a facade for them. For example, if you're like anyone else, you'll tell the phone to dial up a number and the phone will use the SimCard to do that.  If you're a developer, you'll ask the phone for the SIM Card and try to dial up the number yourself, somehow..  If you're like everyone else, when the battery is depleted, you'll plug the charger into the phone and the phone will take care of the details. If you're a developer, you'll remove the battery from the phone and try to charge it yourself, somehow...

 Because the phone is the AR, it uses other domain concepts to do its work and exposes the relevant behaviour for that. Everything you need from that aggregate, you ask the AR (the phone). Some domain objects are hidden, while other are exposed (battery, simcard). The phone acts as a parent for all those objects and it requires them in order to be and behave like a phone.

 However, the charger, the data transfer cable or the protective cover are not part of a phone. The phone works with a charger and it's protected by a cover, although you will say that "the phone has a protective cover". That "has" is not a domain "has" so it's not a hint that the phone AR should have a property Cover.

 In order for a domain object to be considered a 'child' of another object, the parent needs that child as part of definition or behaviour.  If the objects represent domain concepts that only work together, they should be part of an use case.

 If you find yourself treating an AR just a holder for other objects, then there's 99% chance that you're doing it wrong. AR are not containers, are 'high level" concepts which encapsulate other, 'lower level" concepts.  ARs are collaborating with other ARs in order to provide business value.  A Category concept can be defined as grouping posts according to a criteria. The Post AR and the Category AR are unrelated, but they have a collaborative relationship, where a Service can use a Category to group Posts. You can say that the Category concept defines an use case for Post.

 In conclusion, don't rush to code and don't treat the Domain superficially. Even with a quite simple Domain like a post publishing engine, you can fall into traps. Make sure that you really understand the concepts and take you time to identify the the proper 'has' relationships.

DDD: The Aggregate And Aggregate Root Explained

By Mike on 18 April 2012

The Aggregate
This is simple. An aggregate is a group (a cluster) of objects that work together and are treated as a unit, to provide a specific functionality :) . An animal is an aggregate, it has internal organs, limbs etc. Everything works together to keep the animal alive and when we say animal, we imply everything the animal is made up from.  A car engine is also an aggregate, it contains lots of components, that can be aggregates too, which work together to achieve the engine functionality.

But that's not all, in order for the objects to work together they must be consistent together. And to maintain that consistency, the aggregates also enforces boundaries. As a matter of fact an aggregate is a bounded context. We treat the animal as a unit and it just happens that its boundaries are very explicit (a physical body). But let's remember John and the IT department.

The IT dept. is a logical division inside the company, it might have its own offices but it can also be just IT people scattered around everywhere. That doesn't mean the IT doesn't exist, it exists but there are no explicit physical boundaries, there are organizational ones. The IT dept.  pretty much comprises the collection of people,  computers, internal regulations that handle all IT related matters. 

One important thing is to note that an aggregate is a concept and not necessary a concrete object. When anyone in the company refers to IT, to whom or to what exactly are they referring to? For most, IT is just an abstraction, not a concrete person, office or computer. It's the 'something' where you go to solve computer stuff. But you can't work with a something. You need a more concrete representation.

The Aggregate Root
An aggregate root (AR) is a 'chosen' object (an entity to be precise - I'll tackle entities in a future post) from within the aggregate to represent it for a specific action.  When the upper management wants something from IT, they call Andrew (the manager). They ask Andrew for reports and more importantly they tell Andrew what they need the IT to do. The big boss doesn't know and doesn't care about John or other lowly developer (sounds familiar?), the big boss knows that Andrew represents IT and thus it's enough to talk to Andrew to get the job done. And Andrew tells John and others what to do.

This means that the upper management needs to know only about the IT manager and not about others from the IT. In coding, this translates into: outside objects can reference only the AR. Of course, when given a command , the AR will coordinate other aggregates to actually process it, but that's a BC internal concern. The AR also makes sure that the model stays valid and consistent inside the BC.

But Andrew being the AR  when dealing with upper management doesn't mean Andrew is the AR forever and for everything. If Rita has a problem with her computer she will call IT, but not Andrew. Jimmy is responsible for dealing with broken computers and in that context he is the AR. So, another important fact is that AR varies with the context, change the context and the AR is another object. And for that specific context, AR is the 'manager' and coordinates the aggregate's other objects.

A simple object from an aggregate can't be changed without its AR knowing it (that would break consistency), that's why outside objects 'talk' only through the AR. The outside objects might receive a transient reference (temporary, not to be hold) to an inner object  if they need it for a quick operation. If Jimmy goes to the accounting office to check out Rita's computer and in the mean time he lets her using his laptop, that doesn't mean that from then on Rita will keep Jimmy's laptop. The IT will provide a laptop just for the time Jimmy's repairing Rita's computer. Once finished, Jimmy takes the laptop back. The laptop is an object of the AR, that is used shortly for a specific purpose by an outside object. But after the action is completed, the outside object 'forgets' about the laptop.

Now, an AR is always a unit of work so it gets persisted as a whole (to preserve consistency). When dealing with the domain the repository only stores/restores the AR. It wouldn't make sense to split the AR in many objects to be stored/loaded separately.  However, the persistence layer might split them to store them in different tables but that's just a persistence implementation detail. When the application receives a AR from the repository, it will receive it exactly as it was sent, same state, same consistency.

That's all about aggregates, in the next post I'll talk about entities and value objects