Warning: This is an opinionated article and could be classified as a rant if you really want…
The Trend
There’s a trend by software developers to approach domain-driven design as a collection of useful programming/coding patterns and abstractions:
- Entities
- Aggregates
- Repositories
- Factories
- Services
- Value Objects
- Bounded Contexts
- Domain Events
- Etc.
I see this idea popularized on all the social platforms by content creator X software developer with 3 years of experience who is an expert on building distributed microservices using domain-driven design. They can tell you all about creating entities, aggregates, and repositories. And distributed microservices too – as a cherry on the top.
The courses on popular learning platforms are the same. Here’s part of a description from a popular learning platform’s course on DDD:
- Structure your application around domains and entities.
- Establish aggregate classes and determine appropriate behaviors.
- Interact with your domains through events and commands.
I Disagree
I disagree with this code pattern-centric characterization of DDD.
Here are a couple of questions to consider:
- Can I do domain-driven design without using tactical tools?
- Can I do domain-driven design without using strategic tools?
The answer to 1 is yes.
The answer to 2 is no.
Tactical Tools Are Optional
In Vaughn Vernon’s “Red Book” he says:
DDD is about discussion, listening, understanding, discovery and business value, all in an effort to centralize knowledge.
If you aren’t doing these things – you aren’t doing DDD. Period.
Vaughn also writes about a fictitious scenario of developers focused on these tactical tools – calling it “DDD-Lite“:
In fact, they were really using what amounted to DDD-Lite, employing the tactical patterns mostly for a technical payoff.
In other words, it doesn’t matter how many entities, aggregates, factories, services, and repositories you have.
Side note: This is like saying you “do TDD” because you write unit tests and use assertions, mocks, stubs, etc. Sure, those things are useful to know. But TDD is not about individual tests. It’s about using testing as a process of designing and building software. It’s a higher-level plane of thinking.
Strategic Patterns Are Essential
The strategic aspects of DDD are about figuring out what parts of the system matter and which don’t.
For example, where should you focus your efforts if you are building a trading platform for a bank?
- Customer profile management?
- Authentication?
- Interoperability with external banking systems?
Building a trading platform is going to be hard. But at face value, we all know this business will most likely not focus on the first two domains (profile management and authentication). Or maybe I should say should not focus…
Why? Those two domains or systems don’t deliver differentiated business value. They only support the overall system.
Have you ever used a trading platform and really cared whether you could upload a profile image?
But you do care if the trading platform miscalculates your trade and some of your money disappears into the ether.
The Norm: Entitify & Servicify All The Things
In my experience, many (most?) software developers use entities, aggregates, services, repositories and factories to build something basic like a profile management module for their software.
I’ll quote Vaughn’s book again:
Businesses regularly put too much effort into developing glorified database table editors. Without the correct tool selection, CRUD-based solutions treated elaborately are too expensive… if the choice is correct, it should save time and money.
Look at the software business you work in. Are your secondary/supportive products:
- Developed simply using something like CRUD?
- Meeting their budgets?
- Developed quickly?
- Saving money and time?
In my experience, this is not the norm. If the organization is “doing DDD” the norm is using aggregates, entities, repositories, factories, etc. everywhere.
Strategic Design As Protection From Change
In a nutshell, DDD is about talking to the business experts who do the job. To the ones who do the real work you are digitizing. If you aren’t doing that…
Another way to think about DDD is that it tries to help us to answer the question:
- Can you predict which parts of your system & code will change most often?
The implicit premise here: The parts of your system that deliver the most business value and differentiate your business from others are exactly the parts that are apt to change the most.
Supportive modules & functionality like authentication or profile pictures are probably not the pieces of a trading platform that break and change the most, for example.
Your business has to choose where to focus or it will never get things done.
Making Reasonable Predictions
This leads to other questions like:
- Which code modules should you not be awfully particular about?
- Which code modules should you be incredibly careful about?
You could answer this question at the level of code objects like classes and functions. But this level of granularity makes it hard to predict where the most change will be. It’s too narrow and in the weeds. It’s like predicting that an individual stock will do well over the next 5 years.
DDD answers these questions at a higher level. Bounded contexts and domains correspond to larger pieces of the business. You’re making predictions about larger pieces. It’s like investing in an index fund. You get a broader view of the overall market and can therefore make much more probable predictions.
Here’s where DDD practitioners should focus:
- What are the domains and different parts of the business?
- Which parts aren’t going to change that much?
- Don’t fuss too much about these. Maybe even buy an off-the-shelf solution.
- Which parts represent “the secret sauce” of your business – the parts you expect to change a lot?
- If this domain is legitimately complex, then using tactical patterns might help.
- Employing advanced software architectural patterns, coding patterns, etc. might help if they fit the context.
The Source Of The Problem
Is it because software developers like to complicate things more than is necessary? Maybe.
Is it because those overseeing the various business domains aren’t technical and don’t think about Conway’s Law? Maybe.
Because you don’t have access to the people doing the job you are trying to improve/solve? Maybe.
Is it because everyone wants to be a content creator and talk about whatever is trendy? Maybe.
Is it because real DDD is non-trivial, requires real-life experience and depends on the context of your business which is hard to replicate, so we turn to things that we can replicate in order to sound smart? Maybe.
Is it because we’ve had an era of “easy money” via low interest rates that have produced companies which were able to waste tons of money by building projects and products in really inefficient ways but that doesn’t matter because they could just hire more people and throw more money at them and pretend like everything is okay? Maybe.
How Can We Fix This?
I’m not sure how to “fix” this. Individuals need to change and help others to change their minds on this.
This is part of a larger discussion around software developers who over-engineer systems. The code you work on probably doesn’t matter that much to your business in the grand scheme of things. The chances that you’ve over-engineered your code and architecture are high.
But, misunderstandings exist around agile, TDD, SOA, and you name it 🤷. It’s a people problem, as you might say.
Conclusion Or TLDR;
Your business has to choose where to focus or it will never get things done.
It has to on where the true differentiated business value lies.
It needs to think about allocating more resources, time, effort, quality, thought, design, skills, etc. to the places where it matters most.
It means talking to the real people who do the job.
Entities and microservices don’t answer these questions. Entities and microservices don’t mean that you’re doing DDD.
One reply on “Stop Pretending To Do Domain-Driven Design”
word!