I think it's pretty common not to give enough thought to how important the context is. For example, when the GoF patterns [GoF Design Patterns] are discussed and used by developers without prior experience of these patterns, it is typical to forget that there is a context for when the patterns are suitable.
A good idea/solution/anything, but in the wrong context it isn't necessarily any better than a bad counterpart. That's just the way it is.
Let's take a step back before we focus more on the specific context-related concept of this section. First, here's a word on layers and partitions.
Layers and Partitions
Back in 1994, Grady Booch's book, Object-Oriented Analysis and Design [Booch OOAD], was published. It gave me a better understanding of what Jim Rumbaugh's book, Object Modeling Technique [Rumbaugh OMT], had introduced to me a few years before. One such example was layers and partitions. The concept of layers was quite familiar to me, but not partitions the way Booch described them. He saw partitions as slices in the other dimension compared to the layers.
To make this more concrete with an example, two typical layers are the UI and the Domain Model. Two possible partitions might be the subsystem for registering orders and the subsystem for administering user complaints. Both partitions might have a UI and a Domain Model.
Today, just as it was back then, I think layering has received much more focus than partitions. Layering has been a very important way of providing "separation of concerns." You probably have a firm grasp of what the idea is: to live by the principle of Single Responsibility (SRP) [Martin PPP].
In a way, this almost total focus on layering is changing. I think layering has relaxed a bit with DDD, at least compared to the rigorous layering I used in the past [Nilsson NED]. (Well, we are still very focused on factoring out the infrastructure from the Domain Model.)
We discussed layering according to DDD in Chapter 4, "A New Default Architecture."
At the same time, there is an increasing understanding of how you can't create one single huge Domain Model, or at least that it's often too complex, costly, or inefficient to go that route in large-scale situations. I also think Service Orientation (SO) is a driving force when it comes to the increased interest in partitioning. The whole problem simply becomes more evident.
Because of the increased interest in partitioning, the interest in layering might lessen. It's just not as important or beneficial with a rigorous layering design for a tiny partition.
Let's have a closer look at the reasons for partitioning.
Reasons for Partitioning
While layering is often based on technical reasoning, partitioning is often based on organizational reasons. Sure, partitioning could also be done for a technical reason; for instance, a certain partition might become stale faster and might be one we'd like to swap for another implementation later on. The idea then might be to make it obvious and easy to achieve when the day comes.
But again, organizational reasons are important for partitioning, such as because one team takes care of this and another team takes care of that. This is totally in line with a discussion I had with some colleagues about motivations for layering. None of them thought that layering was good to use for organizing a team. That's something I've done from time to time, and (to my mind) with success. What I think they all really meant was that it's a better idea to organize the team around partitions instead. And then the layering is less stressed inside each partition. We will, of course, still see that different people have different main interests and expertise, and we shouldn't fight that. We should just not create a large department of UI developers that builds the UI for all applications, another department of Domain Model developers, and yet one more department of database developers. Out of those two dimensions (if you have to choose), the most important is the domain problems that should be solved, not what technologies to use. Remember that when organizing the team also.
What also matters regarding whether you need partitioning or not is the size of the development effort. For a tiny system, one partition might be all that is needed; for a large system, a good partition design might be extremely important to succeed.
To summarize this, I think that first it's a matter of partitions, and then inside those partitions it's a question of layers, not the opposite.
Let's see if we can couple this to DDD, which brings me to talking a little about the Bounded Context pattern [Evans DDD].
A common question is "How should we deal with complexity?" And just as common an answer is "divide and conquer." Use of hierarchies is one way of dividing and conquering.
DDD is pretty much about hierarchies. One extremely useful tool that I've been emphasizing a lot is the Aggregate pattern, which is a pretty coarse-grained unit. Entities is another unit, and Value Objects is yet another (all found and discussed at length in [Evans DDD]).
If we go in the opposite direction, "up" from Aggregates, we will find that Bounded Contexts isn't the same as aggregates, but rather the same as subsystems or sub-models.
The basic idea with Bounded Context is to be very explicit about in what context the model applies. You should also be very strict about the model and its concepts within the Bounded Context; what is outside doesn't really matter that much.
From a narrow perspective, a good reason for the division into several Bounded Contexts is to be able to think about all the details within one model and to be able to keep it pure. At the same time, from a wider perspective we can think about "large" abstractions that are easy to grasp and think about in overview terms.
A strong advantage of the Aggregate is its boundary. It simplifies life, decreases coupling, and makes connections more explicit. Again we find advantages of a boundary, this time on a higher level with the Bounded Context.
Although I see great value in boundaries, there are also costs. You might introduce a lot of overhead when it comes to communication and performance. As usual, keep it simple and add complexity when you gain more than the cost.
If we bind this to the example I used in the previous chapters, that of the sales order, there might be one bounded context for ordering and another for shipping. This is not how I started to talk about it in my little example, but in a real-world, large scale situation it might make sense from a technological standpoint, and different parts of the organization might very well be dealing with each of those business processes, which might be a good reason for the split.
How Do Bounded Contexts and Partitions Relate?
I've been talking about partitions and Bounded Contexts, but that doesn't mean that I see them as the same thing. It's possible that the Bounded Context is the same as a typical partition. It might also be that a Bounded Context is built up of several partitions instead, but probably not the opposite.
Scaling up DDD Projects
A typical reason for applying Bounded Contexts is that they provide a way of making it possible to scale up DDD to larger contexts. Instead of having one huge Domain Model that a huge team touches, it might make the effort of understanding the model much easier if you split the model into several smaller ones, letting the development groups focus on their own models.
Bounded Contexts might also help preserve the Ubiquitous Language from becoming un-crisp and having loose definitions. Instead what you will get are several Ubiquitous Languages, one per Bounded Context, which is partly a bad buy. But on the other hand, each of these will be more powerful and exact. Rather two good, than one bad.
When you find out that what you thought was a single model has started to have concepts with different meanings and that the Ubiquitous Language isn't as clear and crisp as before, that can very well be a sign that it has actually become two models. Instead of fighting it, it can often be wise to promote this evolution and define two different Bounded Contexts.
It's time to shift focus and talk about another reason for partitioning of Domain Models.
Why Partition a Domain ModelSO?
Assuming that we already have a large Domain Model, why would we need to partition it? This is not a new problem, but I think SO has made the problem more apparent than when compared to other solutions for distributed systems, such as EJB and COM+. In those systems, the partitioning was helpful but most often not so strictly enforced, as is the norm for SO systems.
I'm aware that many SO people don't think from the Domain Model and out, but start with the interfaces instead. As I see it, it's always a bit of each.
This book is not about integration or messaging, but merely about architecture and design for one service or one application. But we relax the focus of the book for a section and have a look at an introduction to Service Oriented Architecture (SOA) that Udi Dahan has written.