What is Domain-Driven Design?
What is Domain-Driven Design? A beginner's guide to the software discipline.
What is Domain-Driven Design?
Domain-Driven Design (DDD) is a discipline for designing high-quality software. Some would call it an applied philosophy, as it comes with tools and methods, making it very practical.
A core promise of DDD is that it helps you deal with complexity in a more sustainable way. It helps to create a software system that not only solves the current problems of today but is malleable enough to adapt to the needs of tomorrow. Software systems tend to have a lot of unnecessary complexity. With DDD’s focus on domain modelling, you make the inherent complexity of the business domain crystal clear, and can weed out the unnecessary complexity. You’ll end up with a system that you can keep evolving at a fast pace.
Unlike most software design methods, DDD looks at the whole system; whether that’s at the micro level of individual bits of code and design patterns; larger structures in code organisation, domains, bounded contexts, and architecture; or at the ultra-large scale with clusters and integrations.
DDD was coined by Eric Evans and popularised through his book, “Domain-Driven Design: Tackling Complexity at the Heart of Software in 2003”(*). DDD comes with a pattern catalogue, that is to say, a coherent set of patterns that software designers were already practising. DDD names and explain these patterns. It also comes with innovations, such as Bounded Contexts. Domain-Driven Design enables a new shared abstraction for teams to use, making it easier to talk about software design.
DDD has a rich body of principles and patterns, so here we will only outline some of the core concepts.
Domain Modelling
"A model is a selectively simplified and consciously structured form of knowledge. An appropriate model makes sense of information and focuses it on a problem." Eric Evans in Tackling Complexity at Heart of Software
To deal with complexity, DDD advises you create and evolve models of the business domain. These models are built in collaboration with domain experts and are used as the basis for the code, the tests, the documentation, the user interfaces, and the conversations about the domain. The advantage of such models, as opposed to the purely technical models we find in most software, is that they encode and preserve a lot more knowledge about the domain. This helps to keep the complexity understandable and manageable, which in turn makes future evolution of the software easier and faster.
We can think of a domain model in somewhat of the same way a scientist thinks of a scientific model. Take gravity for example, it's not perfect, but it's good enough for day-to-day use to know that if you drop an object, it will fall. There are more advanced models like quantum physics that are useful to do certain other things but it's too elaborate for just knowing that if you drop a glass, it will fall to the floor and break in pieces. So a great model is contextual. It’s a set of useful abstractions of your problem domain. As in science, a great model gives you predictability: you can predict how the system will behave, and how you can change the system without breaking it.
Since Eric Evans’ book, there have been many valuable modelling techniques closely associated with DDD including EventStorming(**).
Ubiquitous Language
In any social group, like a team, department, or company, a language will evolve to fit the needs of that group. A language like this is organic, always in motion, often messy and ambiguous. That’s normal, that’s how natural language works. But when we get to system design, we need language to be precise and unambiguous. A Ubiquitous Language is a deliberately designed language, based on the domain, that we can use to talk in precise terms with all engineering and business stakeholders. We use the same language in the code and other artefacts, which helps to make our systems understandable in the long term. At its best, the Ubiquitous Language is used so well, that a non-technical domain expert could read the code and understand what it does (and detect mistakes!). But even without going that far, this shared language makes communication about the software much smoother, so that the resulting software is much more aligned with the business needs.
Bounded Contexts
To manage complexity, we need to split up our software and its models into smaller units. Traditionally, we have used technical separation, such as components, modules and (micro-)services.
DDD does it differently: you look at the domain language and the models first, and draw boundaries around those. Within these Bounded Contexts, the language and the model are consistent and unambiguous. We don’t attempt to have a single universal model across the organisation, as that doesn’t work, and has a high coordination cost. Organising into smaller independent models allows us to make them much better aligned with business needs, and lets us evolve them to continue meeting these needs.
A way to build an intuition for it is that a Bounded Context is an understandability boundary. It groups concepts that need to be understood together, and separates them from unrelated concepts. It’s very productive, as a new team member can quickly learn a small Bounded Context without having to wade through unrelated concepts.
In practice, you’ll still want to separate code into modules or services, but your separation will be much more inspired by the real business domain, as opposed to technical or organisational concerns.
Advantages of DDD
"With Domain-Driven Design, I can bring the code closer to the business. By growing a shared language and better boundaries, the team can have a deeper understanding of the code and how it solves merchant problems in our domain." Senior Developer at Shopify(***)
A core benefit of a mature DDD system is that you have code and artefacts that really look like the problem you’re solving. The code uses the same language as the business stakeholders do, and your shared model expresses business concepts, behaviours, rules, processes, and relationships. Adding, say, a new business rule, becomes trivial: it’s obvious where that fits in, and it’s predictable what impact it will have.
Having a clear model, language, and boundaries enables you to move faster. You don’t waste time on reverse engineering what the code is supposed to do, as it’s clearly communicating intent. It’s often underestimated how quickly you will be able to respond to market changes and customer demands using these techniques.
We help teams implement Domain-Driven Design practices through consulting and training. Learn more about our services.
* https://www.oreilly.com/library/view/domain-driven-design-tackling/0321125215/
** https://www.eventstorming.com/
*** https://aardling.eu/en/insights/how-aardling-helps-shopify-apply-domain-driven-design