DDD: Identifying Bounded Contexts and Aggregates, Entities and Value Objects

By Mike on 31 October 2014

Let me be clear about one thing concerning Domain objects: they aren't either Entities or Value Objects (VO). You can have simple objects in your Domain and you can have objects which have a business meaning. Only an object representing a Domain concept can be classified as an Entity (it has an id) or a VO (it encapsulates a simple or composite value).

Bounded Context (BC)

First thing before starting an app is to identify the Bounded Contexts. Luckily this is quite simple. First of all let's remember that a BC simply defines a model that is valid (makes sense) only in that BC. If you're designing your app as a group of autonomous components (and you should) aka vertical slices aka microservices (for distributed apps) working together, then each component is a BC. For example, I'm working on a Saas app and these are some of the components: Membership, Subscription, Invoicing, Api Server, Api Processor. Each is like a mini app in itself, each has their own domain and thus their own model which makes sense only for that component (BC).

The components being autonomous, they don't depend one on another (at most they know about other's abstractions) so they don't share the model i.e the model of one BC doesn't cross its boundaries to be available in other BC. But, a subscription is related to an account so it might seem that Subscription must know about Membership model. Similarly, Invoicing is related to an account and needs data usually found in Subscription. How do we solve this, without coupling the components (breaking the boundaries)?

Each BC has its very own definitions of concepts even id it happens that they share the same name. An Account is a fully defined concept in Membership but it's just an id in Subscription, Invoicing or any other BC and that's because the BC itself controls the definition. So the Account is not just an id because the Membership Account entity has a property Id, but because the other component said so. However, in practice, a concept which is an entity in other BC will at least be defined as an id in other BCs. But the VO are a different story and each BC really has their own definitions. Of course, some concepts may be generic enough that their definitions will be identical. But that's just a coincidence, and in fairness, if a BC shares a lot of concept and definitions with another, perhaps they should be merged.

What about the data that a BC might need from another? A BC should be like a black box. You don't see what's inside, you know only about input and output. In a message driven app, this means you send commands to be handled and you get events. Those are DTOs and contain all the relevant (in/out)data for an use case. So we have our BC listening to other BC's events. If you really want to keep things decoupled, because you want a reusable component, then you can use a mediator that will listen to one BC then send the relevant data to the other one. That's the approach I've taken with the Invoicing component (so that it wouldn't know about anything Subscription).

So, a BC takes DTOs or commands as input then publishes events as output. A BC model exists only in that BC and all the DTOs are just flatten aspects of that model. Since an event is just a data structure with no business rules attached (consider it a read model ;) ) that data can travel to any other BC that can extract the relevant information from it. In the end, BCs 'communicate' via simple data that only have the role of input/output.

Aggregates

Identifying Aggregates is pretty hard. An aggregate is a group of objects that must be consistent together. But you can't just pick some objects and say: this is an aggregate. You start with modelling a Domain concept. For a non trivial concept, you end up with at least 1 entity and some VO. Regardless of how many entities, VOs or simple objects will be involved, the important things are that you'll have a 'primary' entity (named after the concept) and other objects that work together to implement the concept and its required behaviour. Those together form an Aggregate and the 'primary' entity is the Aggregate Root (AR).

The purpose of an AR is to ensure the consistency of the aggregate, that's why you should make changes to one only via the AR. If you change an object independently, the AR can't ensure the concept (the aggregate) is in valid state, it's like a car with a loose wheel.

Before rushing out to name any entity an AR, first make sure you know the aggregate then make sure the AR really is responsible for the aggregate consistency. An entity acting as a container for other objects is not an AR. The consistency part makes it an AR.

Domain Entity

Modelling a Domain concept is more than coming up with a name and some properties. You have the name 'Foo' then what? If you start thinking about its properties or behaviour you'll end up with a data structure (resembling a table schema) with functions. That's because we think about all things that we want to persist and not about how the concept is defined and used by the Domain. We want to come up with a model fit for everything and that's the wrong approach.

In order to define Foo you start with the use cases of Foo, better yet, implement those use cases as tests. This is how you identify the relevant properties and behaviour, that's how you design the entity. Once you have the interface defined, you can go wild with the implementation. In practice, you'll notice how you start with one entity and you end up with a whole aggregate. And that's how it should be, anyway.

Domain Driven Design Modelling Example: Brain and Neurons

By Mike on 11 June 2014

 I got this question on stackoverflow

A brain is made up of billions of neurons, so if you have brain as your AR you potentially have a performance issue as its not feasible to retrieve all neurons when you want to activate some behaviour of a brain. If I make the neuron the AR, then its not trivial to validate its behaviour and there is the issue of creating new neurons within a brain. Which should be the AR, or should there be some other AR to encapsulate these

I found the use case quite interesting because of the fact that we're dealing with billions of "children". So is the Brain an Aggregate Root (AR)? Is the Neuron a Value Object (VO) or an AR? Assuming that we want to model things as close as we know how the brain works I'll say it quick: Brain is an AR, Neuron is a VO and the Brain will always require ALL the neurons (yes, billions of them) every time you ask for a Brain object from the repository. So I'm saying to load billions of rows anytime you need a brain (sic). Maybe I need a brain too. Or I'm just a good Domain modeller. Here's how it is:

A brain can't function without neurons, a brain needs the neurons. But does it need all of them? Well, let's see... I'm telling the Brain to learn a poem. The Brain will use some neurons to store that information. I tell the Brain to solve a math problem. The Brain will use the same or other neurons to do that. Now, do I (the client using the brain object) know which neurons are used for what behaviour? Or is it an implementation detail of the Brain? That's the point, only the Brain knows how to use the Neurons. It groups them in regions and it might use 1 or 10 regions for one single task. But nobody outside the Brain knows these details. This is proper encapsulation.

So when you need a Brain you get it whole with all neurons no matter how many they are. You don't get only parts of it, because they don't make sense independently. Btw, the neurons probably are distinct for the Brain but that doesn't mean they are automatically Domain Entity. After all, maybe the brain doesn't care which neurons are used. Maybe it cares more about regions and it just tells a region to supply a number of available neurons. Implementation details...

Should the Neuron be an Entity or even an AR? Maybe, but not in this Aggregate. Here, it's just something the Brain uses internally. If you make it an entity or an AR, you'll have something with an information that only the Brain can understand. And if you understand the neuron information then you don't really need the Brain. In this aggregate, Neuron is at most a VO.

But what about the technicalities? I mean there are still billions of neurons. It's a challenge to load them all, right? Isn't lazy loading the perfect solution here? It isn't, because the ORM doesn't know which neurons the Brain needs. And the brain needs to have some virtual properties (let's say the ORM works with private properties) which should load only specific neurons. But what do you do? You create one property for each possible behaviour so that you can load only those specific neurons? And if the Brain doesn't care about a specific Neuron but only about the signature of the data contained, how can you implement that for the ORM to work with? Lazy loading has just complicated things. And this is why lazy loading is an anti-pattern for Domain entities, it has to know domain details in order to know what data to retrieve. And not everything can be put in a virtual property (to allow the ORM to create the proxy), not if you want to make the object maintainable.

The solution here is to load everything the Brain needs to do its job, because it's how the brain works according to the Domain (it needs ALL the neurons) and it's a maintainable solution. Maybe not the fastest one, but you're dealing with a complex notion where maintainability matters more and it isn't like you're using the same object for queries, right? And it's not about the number of neurons, it's about brain's data size. Do be aware that in this case, the Brain and Neurons have a direct relationship in a way that one can't work or it doesn't make sense without the other.

Other cases might resemble this one, but the relationship can be one of association not definition. In those cases, you have grouping criteria and items (forum and threads) or different concepts working together (table and chairs)

Modelling DDD Behaviour And Use Cases By Example

By Mike on 29 April 2014

 Let's take the community's favourite example: modelling an Order. In this scenario we're talking about a very trivial model since it's a blog post not a book.

First of all, what is the purpose of an Order for our Domain? In most of the cases the Order captures what a customer (C) wants to buy from you (products/services), coupon codes that the C want used with that order, a shipping address where the products will be delivered. I keep this simple, I won't involve billing here.

Let's talk a bit about order lines (everybody knows that an order has lines). Each line represents a quantity of a product at a specific price. Since prices change often we really need to keep the price valid at the time C placed the order. But what is a Price? Note that now I'm talking about the domain concept of 'price' . A Price is pretty much always a positive (or zero) value and a currency. 10 is not a price, it's a number. -5 USD can't really exist while a simple decimal is again a number.

Here it's important to ensure we've got the right definition. After all, you are seeing -5 USD (whatever currency) quite often on an invoice or receipt. But is it a Price? Or is it a Discount? Or maybe a loss? So let's define Price in code

public struct Price
    {
        private readonly decimal _value;
        private readonly Currency _currency;

        public Price(decimal value,Currency currency)
        {
           if (value<0) throw new ArgumentOutOfRangeException();
            _value = value;
            _currency = currency;
        }

        public decimal Value
        {
            get { return _value; }
        }

        public Currency Currency
        {
            get { return _currency; }
        }
    }

I've implemented it as a struct (a minor detail), however in DDD this is called a value object . The Price is a domain concept that encapsulates values that will be treated as a single value (in lack of a better term). What's important here is no need for an id, we care ONLY about values and 10 USD is always the same as any 10 USD (as a value not as a concept).

Back to our Order, can we have an order if 0 (none) products were ordered? Can you even say without sounding weird? An empty order is valid order? Not likely. The Order actually needs at least 1 product to be ordered so that the order can exist. This means that an Order is defined by at least 1 order line. This is very important to understand: the Order doesn't have order lines, it's defined by the order lines. No lines, no order, as simple as that.

Here's how the OrderLine looks like

public class OrderLine
    {
        public OrderLine(int quantity,Guid productId,Price price)
        {
            quantity.MustComplyWith(q => q >= 0, "You can't have negative quantities");
            Quantity = quantity;
            ProductId = productId;
            Price = price;            
        }

		public int Position { get; set; }
        public bool IsCanceled { get; set; }
        public int Quantity { get; private set; }
        public Guid ProductId { get; private set; }
        public Price Price { get; private set; }
    }

OrderLine is a value object (VO) as well. This is a bit tricky as the OrderLine does have a kind of id, the Position property (I could have called it Id). But that id' is valid ONLY inside the Order. And really, an OrderLine makes no sense on its own without the Order context. The lesson here is that not everything with an unique identifier is an entity, because it does matter the scope in which the id makes sense. The OrderLine will always be a part of the Order, everytime you retrieve an Order you'll get all the OrderLines. Update: Is OrderLine an Entity or a Value Object

You see that I store the product id and not the whole Product. Why is that? The Product is a domain concept but the whole definition make sense in another context. Here I really need only an id, for this context this is the 'definition' of the product. We're modelling only things that make sense in the current context and we're reusing whole concepts only if they keep their meaning (definition) across contexts. For example, Price is the same concept regardless of the context.

And speaking of general concepts here's another one: Coupon Codes / Giftcards code. Every customer loves these, after all this how they get a Discount . I won't model a Discount in this post (it really looks like a Price ;) ), I've just mentioned it to show you how things come together using a Ubiquitous Language. We have discounts, not negative prices or just a negative decimal.

In this example, the C can use more than one coupon code (I'm very generous) but with a catch. Each coupon needs to target a different aspect of the Order. So you can have a coupon targeting shipping (free shipping if if the order value is above a threshold) or quantity (10% discount rate for more than 10 items bought) or taxes (we pay taxes if the order is above 99$) etc. C can add only one coupon for each category, more than one are ignored.

First, let's define the CouponCode

public class CouponCode
    {
        public string Code { get; private set; }
        public CouponTarget Target { get; private set; }

        public CouponCode(string code,CouponTarget target)
        {
            code.MustNotBeEmpty();
            Code = code;
            Target = target;
        }
    }

Yet another VO. This DDD is full of them, really! Note that again, we don't have just a string named coupon, we have a full domain concept defined here. Ints, strings, decimals etc are language primitives, not domain concepts. DDD is about modelling and using concepts. And the CouponCode is very important concept. Note that there's no behaviour defined, so how is a coupon applied? Not a part of this post, but the CouponCode will be applied when generating the invoice (by a Billing service).

However, the coupon codes needs to be part of an order. And we have the business rule specified above (only one coupon per aspect). It's time to take a look at the Order class

public class Order
    {
        public Guid Id { get; private set; }
        private List<OrderLine> _lines=new List<OrderLine>();
        public IEnumerable<OrderLine> Lines
        {
            get { return _lines; }
        }

        public Order(Guid id,IEnumerable<OrderLine> lines)
        {
            Id = id;
            lines.MustNotBeEmpty();
            _lines.AddRange(lines.OrderBy(d=>d.Position));
        }

       
        List<CouponCode> _coupons = new List<CouponCode>();

        public IEnumerable<CouponCode> Coupons
        {
            get { return _coupons; }
        }
       
        public void AddCoupon(CouponCode coupon)
        {
            //rule - only one cupon per target type

            if (_coupons.Any(c=>c.Target==coupon.Target)) return;

            _coupons.Add(coupon);
        }

        public Address ShippingAddress { get; set; }

        public void CancelLine(int position)
        {
            _lines[position].IsCanceled = true;
        }
    }

A very simplified Order. Note that the Order really needs the OrderLines, passed as a constructor init value. This implements the fact that without an order line the order can't exist. But we're talking about coupons here. So let's focus on the AddCoupon method which implements the business rule. This method is a behaviour of the Order entity. It uses the CouponCode concept so it's also a use case of the CouponCode.

Speaking of behaviours and use cases, there's another behaviour: CancelLine() . You tell the Order that one lines should be cancelled and the implementation is a use case of the OrderLine. But even the Order itself can be part of an use case, for example when generating the invoice (you can't have an invoice without an order).

You see that you can't do 'order.Coupons.Add(coupon)' or 'order.Lines.Cancel()'. It makes sense to let the Order add coupons since it encapsulates how/if a coupon should be added to an order. It also natural that you'd tell the Order what to do with one of its details. The Order contains the business rules that may allow or not the action, also, it's up to the Order to decide how an action should be implemented. It's just proper OOP here.

You'd be happy to know that Order, Price, OrderLine, CouponCode, Address form together an aggregate. It's then obvious that the Order is the aggregate root (AR). But this came out AFTER we've defined the Order concept, as well a other relevant concepts. The point here is that you don't decide the aggregate (root) first, you just model the concepts/behaviour/use cases using proper OOP and the AR comes up by itself.

Also, the AR is not just a container for order lines, it's a full domain concept defined by other smaller domain concepts. I think this is the most common mistake with DDD, to think of AR just as a container for its children (I don't really like to use the semantics parent-children in DDD, it's too CRUD for me) when in fact, it's a bigger Domain Concept encapsulating business rules involving smaller concepts of the same aggregate (excuse the abstract language).

In conclusion, you can do DDD easier if you're focused on modelling the correct domain concepts with behaviour, identifying and implementing the use cases in a proper OOP manner and all the DDD technical terms (some call them tactics) will appear obvious by themselves. This is exactly like using a design pattern, you don't say "Hm, what design pattern should I use today", you just try to code a solution to a problem then you realize you're using/discover a design pattern.

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