A few years have passed since the original formulation, and many things happened to the concept and the community too. This page is an opinionated attempt to describe Domain-Driven Design to a newcomer, easing the burden of browsing through history.
A quick definition
Domain-Driven Design is an approach to software development for high-complexity high-value enterprise software.
It is not an architecture or a methodology. It's a more all-round approach with spans in different layers of the socio-technical stack: from reading business needs and organisation constraints, to good coding practices.
Practices and tools have evolved over the years but most of the core concepts still stand.
- Strategy is embedded in the approach: it's not a one-size fits all recipe.
- Focus on learning: it's the major impediment to delivery of high-value software, so let's put it at the centre of our approach.
- Language(s) as first class citizens of the software development landscape.
- Multiple models is the key for not evolving into a big ball of mud.
- Sophisticated architectural options are fundamental. If all you can think of is CRUDs, you'll have a long way to go.
- Good coding practices are expected. Evolutionary software without solid testing is suicidal.
Not every portion of a large system requires a sophisticated approach. Many features of DDD can be overkill, if applied in the wrong place. But detecting the current business needs, understanding the landscape and sketching a sensible strategy is a good thing to do, no matter what.
DDD suggests to focus on the Core Domain - the high value portion of the domain in its current state - and to fall back to more conservative approaches for other portions such as Supporting and Generic Subdomains.
Big Picture EventStorming can be a powerful tool to understand the current strategy and needs of the organisation, and to detect its current core.
Sketching a Context Map can help reading the political landscape constraints and impediments to a successful project, before wasting tons of money in a project that was doomed from the beginning.
Focus on Learning
DDD is all about learning the intrinsic complexity of the domain, distilling the knowledge needed to build the models for effective software. DDD practitioners are hardly distinguishable from domain experts at the end of a project.
If learning is the bottleneck, then we should draw the consequences and stop trying to optimise for predictable delivery and start optimising for effective learning instead.
The Whirlpool Model is a way to describe a "process" which is not sequential, and it's mainly driven by the quality of the available feedback.
Collaborative modelling practices like EventStorming, Domain Storytelling and Event Modelling are emerging in this problem space, closing the learning gap that traditional requirements gathering could not deliver.
Evolutionary Software is what we're working on. High domain complexity means that we can't learn everything in one shot, be it for our learning limitation on a complex domain - can we understand Finance? - or because the domain itself is continuously evolving. Our first attempt at writing software would be a reasonable approximation, but we'll have to rewrite to get things right.
Collaborative coding approaches such as Mob Programming are getting increasingly popular in the DDD space.
If learning is the scarcest resource to manage, then avoiding to learn unnecessary complexity is a vital need for any successful teams.
Bounded Contexts help to localise the complexity, preventing a lot of and you also should be aware of...
Ubiquitous Language will encapsulate the local understanding so that nobody will have to remember that...
Ubiquitous Language is an original concept in DDD. It describes an ambiguity-free language spoken by everyone involved in the project. However, a spoken language can only be partially defined by a dictionary. In DDD languages becomes tool to determine the quality of our implementation models: translations and misinterpretations are indicators of creeping accidental complexity, while the emergence of Ubiquitous Languages in Bounded Contexts is a sign progress of the learning going on in the team.
Refactoring towards deeper insight is a way to reflect the teams learning into the code. Readable and intention-revealing code will eventually become one with a more precise conversational language.
The shape of the language evolved during the years: while a lot of emphasis was originally put on nouns, a more sophisticated Event-Driven shape of the language has emerged over the years, with Domain Events as building blocks of a business narrative and of a software implementation.
Domain Events are more semantically precise than nouns, and they trigger reactions in software and organisations. Once again EventStorming helps bringing the software language close to the business language, that is more storytelling than data.
Enterprise problems don't have a single model as a solution. In DDD the notion of multiple locally specialised models collaborating for a greater good is captured by the idea of Bounded Contexts.
Different models are optimised for one purpose only, and they can apply different paradigm internally. So you can have an EventSourced bounded context and a simpler/cheaper more CRUD like implementation in another BC.
Context Mapping helps visualising boundaries and purposes of the different models involved, while the Bounded Context Canvas can be a good companion for discussing and quickly documenting the boundaries and purposes of any given Bounded Contexts.
Enforcing model separation in Bounded Contexts - often supported by Anti-Corruption Layers - also allows for a safer development space. Sharing resources is usually a threat on healthy evolution.
I.e. people would not rename concepts in a shared database, or refactor it altogether because they may be worried of breaking other implementation running on a shared persistence. A private persistence support allows more opportunities for safer code evolution, while maintaining safer contracts where explicitly agreed.
In the early days, it looked like DDD was an architecture. In the blue book one architectural approach was described (describing tactical patterns such as Aggregates, Entities, Value Objects, Repositories etc. ) and unfortunately it looked like that was the way.
The real story is that DDD needs strong architectural foundation in order to deliver evolutionary software and the architecture presented in the book (a collection of patterns, on top of the Domain Model) was the only viable option in 2004.
Now the landscape is way more diversified and allows more options:
- a more sophisticated OO approach with Domain Events as first-class citizens, see Vaughn Vernon's Implementing Domain-Driven Design
- Command Query Responsibility Segregation and Event Sourcing, alone or often combined in CQRS/ES
- Functional Languages, see Scott Wlaschin's Domain Modeling made functional.
- Actor Model is another neat way to implement complex, event-driven, domain models, see Vaughn Vernon's Reactive messaging patterns with the actor model.
...and probably more to come.
This is a value that's often overlooked, but it's definitely there. Since DDD deals with high-value portions of your enterprise software it's critical that your organisation keeps control of their software assets.
Core Domain implementations need to be independent from vendor technology, be it a framework, some middleware, or the database. Your business logic should evolve because of the business evolution and nothing else.
Incidentally, vendor independence has been one of the key factor for DDD longevity. There is no such thing as a "DDD framework". SOA started as a reasonable set of principles, then collapsed under the weight of vendor tools becoming greedy and hijacking architectural choices.
There's a lot of convergence with the microservices community, because the Bounded Context idea fits nicely to detect the ideal granularity of services, and because Event-Driven has resulted as a winning paradigm for asynchronous implementation and for better describing the business language.
More about it on this article.
Good Coding Practices
A frequently evolving code base requires safety. Safety can be achieved only when we are in control of the behaviour of our system. This assumes control over our context boundaries - so, once again, Bounded Contexts are a must - and enough testing to feel safe on our codebase.
While not prescriptively dogmatic - DDD is not mandating 100% code coverage - DDD is assuming the ability, and the patience, to write high quality code, and high quality tests.
Hacks and shortcuts - especially the ones creating lock-in to platforms and tools - aren't usually recommended. Separation of concerns is a strong driver at the implementation level too.
The DevOps movement developed largely independent of DDD, but in 2020 having frequent and reliable deployments is accelerating any feedback cycle, so just go for it.
Faster feedback cycles means faster learning, and more team accountability.
Behaviour Driven Development is another approach to software development that tries to close the gap between software and business. Different tools, very similar mindset, and very close communities.
Behaviour Driven Development emphasises the role of Examples to understand the true nature of business expectations, and DDD could not agree more!
To sum it up
After 15 years being part of this community, I have to admit I am still not completely happy with the official definition(s). Maybe I am looking at the wrong thing.
If I really think what's Domain-Driven Design in 2020... it is probably one of the most intriguing and open minded communities in software development. One that could discuss deeply technical topics as well as their implications in the cultural level of the organisation.
Openness, curiosity, mastery and integrity are what is making this community cool, and Domain-Driven Design an increasingly valuable tool for any strategic business software development project.
Learn with Alberto Brandolini
Check out the full list of our upcoming training courses: Avanscoperta Workshops.