7 Biggest Pitfalls When Doing Domain Driven Design

By Mike on 13 May 2013

Relational database mindset masked as DDD

This is so easily recognizable: it starts with data structures, finds one to many, many to many relations, loves the ORM and it knows that lazy loading is a necessary evil. Probably all devs doing this believe that DDD stands for Database Driven Design.

Domain Driven Design it's not about the data or the relations between data. It's about modeling the relevant business concepts and processes. When modeling account and clients for a Bank, you would never hear the domain expert saying: "We have a many to many relations between accounts and clients". You might hear something like: "A client can open multiple accounts.Two clients can share the same account".

Database mindset automatically 'knows' that a Client has many(a list of) Accounts. But the Domain mindset understands that a Client doesn't have an Account. The Bank opens up an account and gives the Client access to it. The Client never has an Account, he's merely an user of Account.

Modeling Domain is a different task than modeling Persistence. Both are important but are different things and require a specific mindset. When modeling asks yourself what are you modeling: business processes or relational database schema.

Treating DDD as a recipe

DDD it isn't a way, a method of how to do things. It's a mindset to design an application. And it's a very simple mindset: the application Design is Driven by the business Domain. There are no steps of how to do DDD and there isn't a formula you can learn. What you can learn from Eric Evans or other DDD experts is how they approached a problem, but nobody can give you a sure recipe of how to do things.

And one big mistake is to think that if guru X did it this way, clearly you should do the same. Every application is unique, what worked in one case might be a wrong and complicated approach for other case.

Starting with technical details

Begin modeling from a technical point of view (what are my aggregate roots, is Customer an entity, should I use an ORM, I have this Aggregate Root so I must have a Repository also etc) instead of the Domain's  i.e too much technical mumbo jumbo and too little 'philosophy'. Bounded contexts, aggregates, entities etc appear naturally when you understand the Domain. The point is: let the Domain guide the code and not viceversa. You don't try to fit the Domain into the programming language or a framework. You are just expressing the Domain using code.

I've seen a lot of debates if a method should belong to an Entity or to a Service. Is it a Domain Service, is it some other Service etc. These are just technical words which just complicate things. Just follow the Domain (the business) and see what it makes more sense from a business point of view, what it naturally fits. I repeat myself: there is no recipe and the technical aspect is secondary to the business aspect.

Being superficial about the Domain

It's easy to mistake the method for the purpose. In real life you put files into a folder. Why do you do it? Is it because you just want a place to put the files and it just happened to be a folder lying around or is it because you want to group the files according to a topic and the folder is the most obvious choice? What is the folder's main purpose: storage or grouping?

Treating the Aggregate Root (AR) as a container

This is a very common side effect of the previous pitfall, it's very easy to consider that all an AR does is to 'hold' the Aggregate's other objects, especially Value Objects. This is tricky stuff actually, and the only way to not fall into the trap is to properly understand the domain.

As an example, let's take the famous Order. Most of the time you'll find the Order as a collection of OrderLines which can be added or removed plus some methods to calculate totals, taxes etc. However.... an Order is not the Cart where you add/remove products until you submit the order. The Order is the list of products and quantities the customer ordered from you. That's it and nothing more and this means the Order is immutable. It doesn't even has methods to calculate totals because the client didn't order totals or taxes. All the order's financial data is in an Invoice. This means you don't add discounts to an Order either, again because the customer didn't order discounts.

The Cart is a container of products and quantities until submitted when it becomes an Order which has an Invoice attached. The Order seems to 'hold' OrderLines but in fact, an Order can't exist without at least 1 OrderLine. A Cart can exists with 0 items in it, it's called an empty cart. Also, the importance of the Order is not that it's (in the end) just a list of OrderLines but a business document. The order lines are just an implementation detail.

As a thumb rule, if all the AR does is to have a list of something, without representing a specific business concept, it's a strong hint you didn't model an AR but a simple container.

Tying the Domain to the ORM, an artifact of the database centric mindset

When using an ORM, the ORM becomes the relational database but without Sql and presented in an object oriented view. Mixing the ORM with the Domain it's like writing Sql from your business layer: a violation of the Separation of Concerns (SoC) principle. The ORM is not here for the Domain, it's here to protect developers from the ugly Sql.

The "One model to rule them all" approach

  • Bounded Context (BC).
    A business concept may have slightly different definition depending on the context. In the Finance BC, a Product might mean only an id and a cost while in the Marketing BC, a product is an id, name and other relevant marketing details. The Inventory BC has all the technical details of the Product. The point is each BC understands something else when using the same concept. And the Inventory definition resemble but it's not the same as the Marketing definition. Even if they share the same name 'Product' they are different models, relevant only in their specific BC.
  • Technical constraints.
    Even if you have only one definition of the Product, if the object is not anemic i.e it is an aggregate root with behavior it will be a technical challenge to update and query the model. You can store it optimized for querying but it will be complicated to save/restore it from the db. You can serialize the object (trivial save/restore) but it's a pain (very slow) to query. In this case you need to have 2 models: one rich for updating and one 'dumb' for querying (CQRS). There's no need to complicate your life, good code is simple, clean code.

You know  you're applying DDD right when the Model is clear and flows naturally. Yes, it's a bit Zen like. And you can be pretty sure that you're doing it wrong when everything is so complicated that you cringe inside every time you have to change something. Remember this thumb rule: if it hurts then you're doing it wrong.

DDD: Persisting Aggregate Roots In A Unit Of Work

By Mike on 1 May 2013

There comes that time in DDD when you have to include two or more Aggregate Roots (AR) in a transaction (unit of work). They can be modified that's no problem, but how to persist them?! We have one repository per each AR and each AR actually defines the boundaries of its own transaction. How can we save all the Aggregate Roots in a Unit of Work?

There are 2 cases:
1. You are using one transactional storage like a RDBMS. In this case things are very simple: wrap the db transaction in a UnitOfWork and see that all involved repositories receive the db transaction via their constructor. This becomes even simpler if you're using an ORM.
2. You are not using a transaction storage or there are multiple data stores involved. Even with a RDBMS, once there are 2 databases involved you can forget about transactions. What to do then?

The good news is that you're using DDD so let's think a bit. What is the main advantage of DDD? You are modelling in code the business concepts and the business processes. This means that the business workflow can tell us how to achieve that transaction.

Let's consider this example: we have an Inventory and an Order. These are our AR and we want to simply move the goods from the inventory to the order, which in code is just something like subtract quantity from Inventory and add the same quantity to Order. A typical transaction.

But let's see how it would be done in the real world. Let's say that we have 2 rooms: Inventory and Order. First of all, you don't just add/take goods from an Inventory without a business reason. Stock is increased when the suppliers delivers the goods and decreases when the goods are moved to the Order (or other business activity). Same with Order, goods don't just appear from thin air. Usually they come from the Inventory. This aspects are important in understanding how we should model the transaction.

So, we want to move 3 goods from Inventory to Order. This means that you take the 3 items and transport them to the Order room. In this period of time, the Inventory will have (stock-3) items, while the Order is unchanged. But this is not a problem, it's something normal, you can't just teleport things around and even if you could, there will still be some slight delay. Until the items are put in the Order room, we can say that there is some inconsistency with our inventory but that doesn't bother anyone because things will become consistent quickly.

The goods arrive in the Order room so the transaction is successful. But what if there is a problem? If the Inventory doesn't have enough goods, then nothing will be sent to the Order and the transaction is refused on the spot. But what if the Order refuses the goods (because it already has them)? In that case, the natural way is to return the goods to the inventory. Once returned, the Inventory will have the same stock as before while the Order doesn't change anyway. It's a real life rollback.

Knowing these things, it becomes trivial to implement them in code. But here is a tiny catch: it requires a message driven approach and being very comfortable with the concept of eventual consistency.

So, we have Inventory and Order aggregate roots used in a unit of work. Instead of doing: begin transaction -> modify inventory -> modify order -> save inventory -> save order -> commit , now we'll use the workflow as it happens in the real business.

You don't say to Inventory: 'substract 3 from stock" you say: "Inventory AllocateQuantityForOrder". If it can do it, the Inventory modifies its state then generates an event: GoodsAllocatedForOrder. One of the handlers of that event will update the Order: ReceiveGoodsFromInventory. If all it's ok, the Order change its state. If not, the event handler will issue a ReturnGoodsToInventory command, which is basically a rollback for the Inventory.

And here you have it, a transaction involving 2 aggregate roots that doesn't depend on a transactional storage. Let's see the differences between these 2 solutions.

First option is the conventional one, the simplest to understand and to use but:
- it requires at max one transactional storage.
- it requires that the modifications be made in the same time, you can't span the transaction over 2 web requests for example.
- you can't use more than one storage.
- poor scalability.
- it doesn't leverage DDD.

Second option is clearly a bit more exotic (if you're not used to message driven apps) but:
- it takes advantage of DDD thus it's modeled by the business process, so it's a natural fit.
- works in a distributed environment.
- it's storage agnostic.
- it can be scaled easily.
- it requires good developers and a proper understanding of the Domain and being comfortable with message driven architecture.

I favor the second approach, but the first option can be the pragmatical solution for some cases. It's important to take your time to think and choose what option fits your app better. Remember that the devil hides in the details so don't be hasty about your decision.

Domain Driven Design: Aggregate Root Modelling Fallacy

By Mike on 15 January 2013

I've just come to realize something about DDD. Most of the time we're doing it wrong. We are so quick to learn it as some recipe and to apply it almost blindly, we don't take the time to understand the subtility of the concepts. We jump right away to consider the first impression, the peek of the iceberg, as the real concept. And in the mean time we're breaking the Single Responsibility Principle (SRP) too.

Let's take as an example a forum engine. The 'standard' DDD approach we usually do is to have a Board Aggregate Root (AR) modeled more or less like a container of Threads and other Boards. Of course, a Thread is itself an AR. Adding a new thread means something like: get Board from repository, Board.Add(thread) , repository.Save(board). But then the question arises:"What if my forum is so big it has 100k of threads?" Loading all in memory just to add a new one is clearly a performance problem.

How about if I want to change the name of a board? Populating the entire board object again is a problem."Don't worry Mike, there is the concept of  lazy loading" you might say. Yeah, about that... while it solves the loading of everything problem, it just introduces another: now your AR depends on at least one repository. Or worse, on the ORM like most people do it. You're doing DDD to have decoupled, maintainable code but you're coupling a domain object to a persistence detail. Great! It's like all that procedural code that uses classes. "Hey I'm using class and private, I'm doing OOP".

Ask yourself when the AR needs to hydrate. If it's for querying purposes, you already have a solution: it's called CQRS (Command Query Responsibility Separation) and it works great. Really, you just need to have a separate model for querying (a read model) and keep the domain model to model the representation of the business concepts and processes.

But if (like in the example above) we need to add a child item to the collection? Are we back to loading 100k threads id just to add another one? Well, let's think a bit. What is the purpose of a Board? Why do we have boards in a forum? To store threads in them? Or to organize items? I 'm saying items because you can 'put' in a board both threads and other boards.

The purpose of a board is to organize things. A Board is an organizational unit, providing a criteria to group items together. It's not a container! It's not a storage! It's a criteria to group things together. In fact, you don't put threads in a board, you organize threads according to a criteria.

A members group is a criteria (usually permissions) for grouping members. But when you 'put' a member in a group, in fact you associate permissions with a member. So John can be a moderator for Board A, a simple member for Board B and again moderator for Board C. John isn't actually put in a group, John is associated with a permission based criteria. Another example is a VIP group which simply is the criteria to group members according to their premium subscription.

For an even more clear real world example. You want to buy bread. You want the bread to be cheap and healthy. You just created 2 categories to organize bread: based on price and based on nutritional quality. You go to the store and see a bread. You check the price and then you say:"Ok this bread is cheap". What did you just do? You 'put' the bread in the cheap category. Without even touching the bread. The bread is there on a shelf. But it's also 'in' the cheap category.  Well in fact, it's associated with the cheap criteria.

Next you check the ingredients. Good, the bread seems to match the healthy definition for you. So now it's part of the healthy category too. The bread is still there on the shelf, but it's also in 2 categories. How come!? Magic!

I think it's obvious now that things that at first sight we considered to be containers, turned out to be something else. You can say that a category has posts or you add a post to a category, but that's just bad choice of words. The category is not a container for posts, is an organizational unit for posts. Its purpose is not to store stuff, its purpose is to organize them.

Like I've said in the beginning, we need to understand the actually meaning of a domain concept not to hurry up with a trivial approach. Once we understand what a concept really means, we know about its responsibility. Then we apply the SRP by not adding other responsibilities that seem to 'fit naturally' with the object (it's like the object shouting in your face: "Don't you think I should be doing that too?").

Next time when you are in front of an AR with children and lots of data, ask yourself what is the meaning of that concept according to the domain context and try to see if the AR respects that and doesn't try to do more things at once.

It's quite common to say that DDD is hard. I realize that is not hard once you understand the principles, but it's tricky. VERY tricky.

Why Domain Driven Design is Hard

By Mike on 28 June 2012

Well, in fairness, it isn't. Yes, it's a bit tricky to understand at first what's all the bounded contexts, aggregates, entities and value objects things about, but that's about it. Or isn't it?!

The biggest obstacle in understanding DDD is you. Yes, YOU! Your mindset, to be more precise. When you're used to think in certain ways, it's very hard to forget about the 'old' ways and pretty soon you'll be doing what you think is DDD, but in fact it's a mix of 35% DDD and 65% old habits.

Probably the biggest thing is that the db is not the center of everything anymore. You don't start with the db schema design, you don't go defining the ORM entities and you don't wrongfully think that the EF entity is a domain entity. The domain is the center of everything and you must forget about other implementation details. And that's maybe the second hardest thing: you need to have a pretty clear understanding of the app layers and more important their concerns. If you have only a vague idea about them you won't get very far with DDD, in fact it will be MUCH harder and you will conclude that DDD is VERY HARD :)

One other thing is that, once understood, DDD is pretty simple and straightforward but with a catch: there are no rules, only guidelines. This means there aren't cookie cutter solutions, no magic answers and no ultimate techniques. Ok, if you really want some hard rule here is one: it depends on the context. Yes, everything depends on the context, one perfect solution for one context is not appropriate for other context, in the same app.

So, you have to think and to analyze the problem, using only a few concepts and guidelines in order to come up with a naturally flowing solution, implemented as maintainable code. And that's hard! Thinking and coming up with good solutions is hard. That's why a good developer is well paid (or they should be anyway) and that's why Evans himself says to not use DDD everywhere. You need experienced developers who can navigate only with a simple compass and a bit of clear night sky and those developers are expensive. Add to that a fairly complex domain and watch the costs rise. And for simple apps (ha! define simple), this approach is just overkill. A senior developer will just waste time while a junior developer will just slap together some pocos (anemic domain), validate some rules and send everything to a db (which is not DDD in case you wonder).

In  conclusion, DDD is a tricky beast: confusing but simple, clear yet very vague. Because you need skilled people, it's expensive from the start and not everyone can afford it. And for many problems, it just doesn't worth the trouble or the cost.

Domain Driven TDD

By Mike on 26 April 2012

As I saw Greg Young's Simple Testing presentation, I just knew I HAVE TO USE that. Just to serve you a sample to peek your interest, Greg shows a way to do something very similar to BDD (but it's still TDD) without a complex framework.  So instead of having just a 'a_null_argument_throws' test passed, you also get context information in a human friendly way. And that with a basic setup which can be coded in a hour or so.

If you're gonna google for Greg's Simple Testing 'Framework', you'll find that it contains a lot of code which doesn't resemble much the code he presented on the slides. But that's not a problem since the concepts are the most valuable bits.

So I made my own setup as it can't be called a framework, not even a toolkit, it contains basically 2 classes and one of them is just to prettify things. Long story short, the idea is to have a more BDDish way of writing tests but with minimum of effort and maximum of info. That is having this

public class Page_State:Fixture<Fulldot.Domain.Common.BasicPage>
   {
       public Page_State()
       {
           _model = Given.AnExistingPostOrPage();
       }
       [Expect]
       public void it_cant_be_published()
       { 
          _model.InAnyStateExcept(PageState.Published).And().WithoutContent();
           Assert.False(_model.CanBePublished);
       }
}

shows this

Scenario: Page State
Given:
    an existing post or page in any state except Published and without content
Then:
    it cant be published

And that just using a standard testing framework, in my case xUnit.Net. Note the [Expect] attribute, it's just a class extending the [FactAttribute] of xUNit. I'm using it for the whole purpose of showing the test name with the underscores replaced to spaces. Yeas, that's it.

The Fixture<T> class features some complex code

public abstract class Fixture<T> where T : class
    {
        protected T _model;
        public Fixture()
        {
            Console.WriteLine("Scenario: " + GetType().Name.Replace('_', ' '));
            Console.WriteLine("Given:");
           
        }
 }

Yep, that's it. The actually tricky part is not in this simple herlpers, but in how you setup the tests. And the secret is a Fluent approach.

The above sample is from the test units for the Fulldot blog engine. Let's dissect the code.

I setup the context in the constructor (standard in xUnit.net). 'Given.AnExistingPostOrPage()' communicates the initial context and it looks like this.

public static class Given
    {
        public static BasicPage AnExistingPostOrPage()
        {
            Console.Write("\tan existing post or page");
            var p = new Post(1);
            p.DisableEvents();
            p.AssignId(1);
            p.SetContent(New.CommonPageContent);
            p.EnableEvents();
            return p;
        }
}

The actual implementation is not important. What's important is that I setup the relevant object while providing information about it.

In the actual test I have ' _model.InAnyStateExcept(PageState.Published).And().WithoutContent();' . I think it's very easy to understand the intention of this code. And once again, I'm using a fluent approach.

public static BasicPage InAnyStateExcept(this BasicPage pg, PageState state)
        {
            Console.Write(" in any state except " + state);
            pg.DisableEvents();
           var s = PageState.Draft;
            switch(state)
            {
                case PageState.Draft:s=PageState.NeedsReview;
                    break;
                case PageState.Published:
                case PageState.NeedsReview: s = PageState.Draft;
                    break;
            }
          pg.ChangeStateTo(s);
            pg.EnableEvents();
            return pg;
        }
public static BasicPage WithoutContent(this BasicPage pg)
        {
            Console.Write(" without content");
            var cmd = New.CreatePostCommand;
            pg.DisableEvents();
            cmd.Content = null;
            pg.SetContent(cmd);
            pg.EnableEvents();
            return pg;
        }

I think by now it's obvious why it can't be made into a generic framework: the fluent interface depends on your domain. Or how Greg put it: "it is a subset of the Ubiquitous Language". This also means that this approach works very well when you're testing the Domain. For simple assertions you just use the 'normal' tests. You won't lose any value.  In fact, this style makes the most sense when testing complex use cases, for the majority of the situations it's overkill.

A few notes:

  • This fluent TDD has the obvious benefit of providing self-explaining tests. It greatly reduces the time you need to READ and UNDERSTAND the tests 6 months later. The non-programmers can read the output too.
  • It makes you think better about the domain objects and helps you design them according to the use cases. 
  • It has an upfront cost because you need to spend more time in order to properly structure the code.
  • But you do get more maintainable code.

DDD: Entities And Value Objects Explained

By Mike on 20 April 2012

There's no DDD if there are no entities or value objects lying around, eh? Before we continue, let me clear up a thing: Entities and Value Objects (VO) are concepts. Depending on the context, an object can be both and its implementation can be slightly different.

The point is you don't start with: let's find the Entities and each entity will be a subclass of an abstract Entity class. You try to model a problem or a solution using objects. The fact that in a context one will be used as an Entity will simply emerge when you design the model. Very little matters for the app that an object is an Entity, however it might matter when you communicate with other developers.

The Entity

An object with an id is an entity. That was simple, wasn't it? You put an id in a calss, when you still want to refer to a certain object even if all the other variants have changed. That's why yoy put an id, the id never changes and you know that you will always get the same object when you ask for the User with Id = 8. The user object can change the name or email properties, in fact it can change all the properties it will still be the same User with id 8.

The Value Object

This is an object without id. If any of its variants changes, the object is considered to be another object. Most of the time a Tag is a VO. Change the tag name and suddenly you have another tag. That's because the object's identity is its value (hence the name Value Object).  One thing to note is that is good practice to make the VO immutable, that is once it's created it can never be changed. That doesn't mean it can't have behavior. But that behavior can't change state, it will just return another object.

You may wonder why you should use VOs. The Value Objects are ideal to encapsulate bits of domain. If something is a VO, I know that something is valid and immutable. An Entity might change state at any time but the VO is always 'stable'.

Is it my object an Entity or a Value Object?

That's the most tricky part and here is where everyone has problems. But here's a tip that will save you lots of headache: a concept from the domain can be an entity or a VO depending on  the context. This means that before you decide that object X is an entity, first you have to identify the BC where object X will be used . You'd be surprised how often you'd be using Value Objects.

You have a car, which among other things has 4 wheels and a engine. Is it the engine an entity ? Well, let's suppose the car works with the engine type ENG-3. When the engine breaks, can you replace it with another engine of type ENG-3? Pretty much yes. In this case an engine is a VO. That's because you don;t care about that specific engine, you care only about an engine (any engine) that is compatible with your car.

But, if you're a car engine manufacturer, you want to keep track of each engine produced. In that case, the engine is an entity as the company cares about each specific engine. If you built your own engine for your car, then the engine is an entity because even if it's broken, you won't replace it. You'll repair it and change its components but it will still be the same engine.

You buy a book form the library. If you lose that book and buy another one and you don't care which is which, then the book is a VO. But if the first book you buy is signed by the author (a very limited edition), then it's very hard to replace it. You care about that specific book, another simple copy won't replace it. That book is an entity.

You have a heart. You do care about your heart but you can replace it with a compatible heart and your body can function further. The heart is a Value Object. You, as a person, are you an entity? Well that depends too. For your friends and family you are, no matter what you change about yourself is still you.

 However, for your employer you might be just a VO. If your employer just need someone with C# skills, anyone who knows C# can qualify. Today is you, tomorrow will be another person (perhaps with a lower wage). In this case, the developer is a VO. But if you're John the star developer, you are an entity. John can't be replaced with another developer. John matters for the company because he is John. The big boss knows about John, not about a C# developer.

As you can see, everything matters according to context, that's why it doesn't make sense to start modelling by saying: I have this  entity. You have an object and the domain context will reveal if it will be treated like an Entity or like VO. A very BIG confusion happens because of mixing layers. Especially when using an ORM, there you can have Entities which are a detail of the ORM. In other cases you might want to store some objects using an id. But that id makes sense only when dealing with the db (a different context). The Tag is a VO for the Domain, but it's an entity for the Persistence.

So design your objects to form a valid model only for a specific context. Just inheriting from an abstract Entity class doesn't mean that object IS a real Domain entity and if that base class doesn't have some common behavior useful for ALL entities, don't do it.

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

DDD: The Bounded Context Explained

By Mike on 17 April 2012

What is a Bounded Context (BC) you ask? Well let's see the definition
"The delimited applicability of a particular model. BOUNDING CONTEXTS gives team members a clear and shared understanding of what has to be consistent and what can develop independently."
All clear now? Yeah.. thought so.

BC  is one of the hardest DDD principle to explain, but it is probably the most important , because you can't do DDD without a BC.  So, you have to understand how to identify a BC before actually getting to Aggregate Roots, Aggregates, Entities and Value Objects. So let's try again: A context means a specific responsibility. A bounded context means that responsibility is enforced with explicit boundaries.

Meet John, a developer at the company X. Meet Rita, she's an accountant at the same company. John works in the IT department. Rita works in the Accounting department. The IT department is a bounded context. It has the responsibility to handle everything IT related in the company. The Accounting department handles everything accounting related, including payrolls. Both have very precise responsibilities and their boundaries are pretty explicit.

I'm not talking about the fact they're in different offices. They have their own internal organization, their own internal rules, employees etc. John doesn't go into Rita's office and modifies the payroll and Rita doesn't go to John's and modifies his code. They could but it would be such a scandal, because if they do that they would be overstepping their boundaries. If Rita finds a bug in the accounting software (developed in-house) she calls the IT department to handle it. She doesn't fire up Visual Studio and starts messing with the code. It isn't her responsibility and she doesn't know how to do it anyway, even if she knows that VS is the program used by John to write code. In fact, VS would be a very strange software on an accountant's computer. Like wise, the payroll files or invoices have no place in the IT department.

Of course, when John has a problem involving payroll he asks Rita to look into it. Both are respecting each others boundaries and act according to their responsibility. But the IT department is itself organized in 2 groups:  the software development group and the administration group. The first group implements features and fixes bugs. The second group handles servers. Each group is a bounded context as well. They have their own responsibility and explicit boundaries. The DBA doesn't write C# code and John doesn't mess with server configs. Everyone acts according to their responsibility and within their boundaries.

So, the IT department is a BC. John is part of its model. In fact everything which makes sense (developers, servers etc) is part of the BC and it should be consistent inside it (the developers should write software and not be asked about invoices). This means that Rita has no place in IT and she shouldn't handle anything IT related. Rita is part of the Accounting BC. She might be visiting the IT office but then she's just a visitor passing by, she has no meaning for the department and nobody expects her to write code or act as a developer. John might have a crush on Rita and spends some time in her office, but that doesn't make John an accountant.

We pretty much see that those BC are kinda autonomous and they don't overlap. Furthermore, if an object from one BC (X) goes to other BC (Y) it doesn't mean it's now part of the latter, it's treated just like a simple object with no meaning for Y. So they are almost independent but how can they work together? I mean the IT and Accounting have to work together from time to time. They do that by talking to the right person :) . When Rita needs a new software feature, she can tell John, but John's manager (meet Andrew) ultimately decides if and what features will be added.

Andrew is the man to speak to when you want new features or even to fix some bugs. Andrew is the IT manager and he tells John (or anyone else from IT)  what to do next. Rita can't ignore Andrew because this is the rule in the IT department: Andrew decides. You have to present your ideas the way Andrew wants them or else they're refused. It goes without saying that if the demands have no meaning for IT they are automatically refused. Andrew is the Anti Corruption Layer (well he's also the Aggregate Root at least for some tasks- I'll talk about that in the next post) of the IT BC. Nothing gets past him and what passes by, it's adapted to fit the IT department's internal organization.

These examples are simple but what about our code? We do want our BCs to be decoupled so BC1 should not know about BC2. Well, the idea is that one BC should not know about the internals of other BC, those two can use common objects (DTOs) to pass messages directly one to another or a specialized adapter which knows how to talk with both BC. Depending on the situation, it might make sense for one BC to depend on other (what's the purpose of the ProductsRepository if it doesn't know about Products?!) but again, it depends on  abstraction not on actual implementation. The coupling is always because of depending on implementation.

Wow, long post, but I hope now you have a much clear understanding of what a bounded context is. Here is some examples of common bounded contexts: the application itself, the UI layer, the Domain Layer and perhaps the smallest BC of them all: the object, any object.

Just Stop It! The Domain Model Is Not The Persistence Model

By Mike on 7 April 2012

I think 90% of times I see a DDD question on StackOverflow, it's something like this: 'I have this domain object' and the code shows an EF (Entity Framework) or NH (NHibernate) entity.

NO! This is WRONG (99% of times anyway)!

I've said it before and I repeat it:

  • The Domain Model models real-life problems and solutions, it models BEHAVIOR.
  • The Persistence Model models what and how data is stored, it models STORAGE STRUCTURE.

See? They have pretty different  purposes. The domain is the reason the application exists and everything gravitates around it. The domain should not depend on anything,especially not on a persistence IMPLEMENTATION DETAIL like EF or NH. When you design the Domain Entities, they don't know anything about persistence. Persistence, database, doesn't exist.

When you design the Persistence Layer, that layer serves the Domain and depends on it. So the persistence needs to know about the domain but not vice-versa. You design the persistence entities for storage purposes and to match the ORM's constraints (like making all the properties virtual). So you'll have Domain Entities and Persistence Entities, each with their own different purposes and implementations.

Yes, they do resemble and sometimes can be identical (when the domain is very simple) but that's nothing more than a mere coincidence. Every time you're modeling something in a repository or using an ORM , you are modelling the persistence NOT the domain. There is a reason Eric Evans recommends to start the app with the domain and to IGNORE anything db related: the Domain should not be tainted with infrastructure details, because most of the people start everything with a database centric approach. And once you start with the db, everything will evolve around it and will be constrained by it. But you don't build the application for the database, you build it for the Domain, the database is just a Persistence implementation detail.

In conclusion, repeat after me: the Domain Model is NOT the same as the Persistence Model. Each serve a different layer with different responsibilities.

Entities vs Value Objects by Example

By Mike on 10 February 2012

Rule of thumb: Entities have an unique identity and one entity can't be substituted for another just because they have the same data. Value Objects have no identity and they can substitute each other if they have the same data. Any change to a value object means a new value object is born. An object can be an entity or a value object depending on the context.

A post, a comment or a product are entities because  they have an id and changing some of their properties doesn't change the resource we're working with. It's one of the reasons you work with ids instead of the whole objects.

A tag is a value object. Change the value of the tag and the tag changes as well, becoming a different tag.

A category is an entity. Changing the category name doesn't change the category itself. All the resources from the category still point to the same category.

A coin is a value object. You can substitute one coin with another providing they have the same purchasing power.

A lucky coin is an entity. You care about that coin in particular and you can not substitute it with another coin.