Domain-Driven Design, that’s what you use when you’re building Microservices. It’s a technique that can be used to cut monoliths into small bits, and it’s about Aggregates and Event-Sourcing. Or is it?
The book Domain-Driven Design by Eric Evans first appeared in 2004. It’s a book about communication, language, context, and models. And it’s a book about object-oriented programming and design patterns.
In essence, Domain-Driven Design is about creating a solution that reflects the problem at hand. It’s about designing software together. Not just the development team, but both the development-team and domain-experts.
Domain-Driven Design is about shared understanding.
The ubiquitous language
Assumptions are the mother of all screw-ups. You ask for a feature, the team thinks they understand, and they end up building something different.
Consider storing something in a database, for example. Sounds pretty straight forward… But somebody from the finance department may refer to their Excel-sheet when they say “database”. A developer probably means an instance of a SQL server. It’s the same word, but it has a different meaning.
Speaking the same language is the cornerstone of effective teamwork; Having a common understanding, having a language in which words mean the same thing to everybody in the team: A ubiquitous language.
Complex things are hard to comprehend if they’re not visualized. Doodles on a whiteboard are hard to convert to code. Alberto Brandolini invented a technique to solve that problem: A mapping-technique called Event-Storming, to collaboratively create a common understanding of a process.
The ubiquitous language has a purpose. The words of the ubiquitous language are the names of the objects in the code. To be more specific: They’re the names of the domain-models. That makes communication between the development team and the domain-experts more effective.
A model is a representation of something in a way that makes sense in a given context. A different context requires a different model. Using the same model for different purposes can work counter-productive.
Imagine your business is building and selling houses. A carpenter needs a model to build it, and a marketeer needs another model to sell it:
The model on the left has lots of technical details the carpenter needs to build it correctly. But they are distracting to a potential buyer. All they care about is what it would look like with the furniture in it. Imagine trying to combine these two models. It’s just not going to work…
A business process can be captured in a domain model. Currently and unfortunately, it’s a common practice to create one big model that can be used for every use-case. Domain-Driven Design advertises the opposite: Represent objects differently, depending on the context in which it is used.
Bounded Contexts are the contexts that apply in the business. “Customer” means something different from a customer-relationship-management-perspective, then from a shipping-perspective. Each bounded context needs its own domain-model and is usually maintained by one team.
Aggregates, entities, and value-types
The validity of the state of an object depends on the context in which it is used. Every context has different business rules. Using the same model in different contexts makes it impossible to encapsulate the business logic that applies in the domain object. It can only be validated outside of the domain. As a result, the business logic gets scattered and duplicated all over the code-base. The chances of bugs increases and maintaining the code-base becomes more difficult, as a result.
To have a model for a specific purpose, applied in a single context, has a huge benefit: It allows the developer to code a class that can protect its integrity.
Instead of having other classes assign values to the domain-model, the domain model can have methods to assign values and to validate the correctness of these values before applying them. As a result, the business logic will be in the domain-model, with a lot less duplication as a result.
Imagine having a taxi-cab domain, with a cab-entity. This is what the code would look like:
Typically, entities in domain-driven design have public getters, but private setters. The method that sets the value, is a method with a name that makes sense in the context. It protects the business invariants.
Create separate value-objects. Rather than passing primitive data-types to a method. Mistakes are easily made. How will you validate you didn’t mistake the longitude for the latitude?
“Make the incorrect inexpressible”
Harden your code-base against mistakes. The Domain-Driven Design book describes a series of programming practices to achieve that:
- Value objects represent the immutable objects in the domain. Like Euro’s, Kilometers for example.
- Entities represent things that are mutable. For example a Cab. It has milage, it has a diver, and so forth.
- Aggregates are an aggregation of entities and values within a consistency boundary.
The value-objects, entities, and aggregates are the domain model. Find a complete code-example here.
Distilling the domain from the conversations between various people in the company is one thing. But these domain-objects don’t do anything by themselves. The need to be used by something.
A company has objects and processes. Consider a taxi-cab company. These cars don’t drive themselves. There’s a process. A cab driver enters the cab, he gets called by dispatch and they tell him where to pick up the next customer.
Use domain-models in a service. The service describes the business-process by invoking the domain-objects. Like so:
(Review the complete code-example here.)
The Domain-Driven Design book starts with several chapters about technical patterns. The chapters about the ubiquitous language and the bounded contexts follow. Event Storming isn’t mentioned in the book either.
Alberto Brandolini’s Event Storming had a big impact on Domain-Driven Design. It made it possible to design aggregates, entities, services, and so forth, with domain-experts that don’t know anything about IT.
Today’s Domain-Driven Design focusses on communication over coding things in a given way.
Also, note that the Domain-Driven Design book was written in 2004. Cloud did not exist yet, neither did Microservices, Event-Driven-Architecture nor CQRS. Event-Driven Architectures with event handlers and command handlers can easily be used in combination with Domain-Objects. And a lot of people do so.
Domain-Driven Design is a book that was written by Eric Evans in 2004. It describes a way to create a rich domain-model by collaboration between business- and IT.
Domain-Driven Design is about designing models. About designing the simplest model that works in one single context. Find the contexts in the domain, and find the correct entities, aggregates, and value-objects as a result of that.
Use several patterns and concepts to make the incorrect inexpressible in your code, making it harder to write buggy code. Name domain-objects like the domain-experts call these objects in real life, to make communication easier.
Visualize complex things to make it easier to share knowledge about it.