Or: Why Suffixing Classes Entity Doesn't Make You Strategic
Let’s get straight to the point: most people doing "DDD" aren't doing Domain-Driven Design. They're naming classes after the tactical patterns in the book. That's not DDD. That’s cosplay.
I say this not to gatekeep, but to clarify: Domain-Driven Design isn’t a checklist of patterns. It’s a mindset. A strategy. A way of seeing software not as code, but as a model of a shared understanding between domain experts and developers. The moment we reduce that to “put your Repos here, Entities there, call it an Aggregate Root and go home,” we've missed the whole point.
The Tactical Pattern Trap
The original DDD book introduced terms like Entity, Value Object, Aggregate, Repository, and Service to help express your domain model. But somewhere along the way, these names became an end in themselves.
People slap "Repository" on a class that just wraps a data access layer and think it’s DDD. They create folders called "Aggregates" but couldn't tell you what makes a good aggregate boundary. That’s DDD jargon, when we should be using our domain's specific jargon (hint: Ubiquitous Language)
These tactical patterns are useful, but only when used in service of the model. Not as decorative labels.
Here’s a tough question:
When was the last time you worked directly with a domain expert to shape your model?
Not stakeholders. Not product. I mean someone who lives and breathes the problem space. Someone who would say, “No, that’s not how first in human trials work” and help you fix the mental model.
If that’s not happening, it doesn’t matter how many “Aggregates” you have. You’re not doing DDD.
The Heart of DDD is strategic, not tactical.
The strategic patterns in DDD—Bounded Contexts, Ubiquitous Language, Context Maps—are where the real power lies. They're also the parts that rarely make it into your code editor.
Why? Because they’re hard. They require conversations, missteps, negotiation. They expose organizational friction. And most of all, they demand that developers care about the business, not just the system.
But they also unlock clarity. Once you understand where your boundaries lie, you stop trying to model the whole business in one place. Once you share language with domain experts, your code starts making sense. Not to just other developers, but to the people who matter.
And here’s the kicker: you can do all of that without ever using the suffix "Repo".
So What Should You Do Instead?
Forget the patterns for a moment. Start here:
- Talk to a domain expert. Not just once. Regularly. Let them poke holes in your model. Be wrong. That’s part of it.
- Use their language. Literally. In code. If they call it a "Serious Adverse Event", you call it that too.
- Draw the line. Define your Bounded Contexts. Don't mix vocabulary from different subdomains just because it’s convenient.
- Think in terms of behavior, not data. What does this model do, not just what does it store?
- Isolate the technical noise. As developers, we deal with plenty of technical subdomains: SQL queries, serialization, HTTP, queues, and more. These are unavoidable, but respecting the spirit of DDD means ensuring the domain model isn't polluted by them. Let the glue code live at the edges, and keep your abstractions clean—no leaks.
If later, your model starts to look like the tactical patterns, great. But let them emerge, don’t force them. They will, if you keep complexity in manageable doses.
Final Thought: DDD Is a Discipline, Not a Template
DDD isn't about how your packages are structured. It’s about how you think about your code and how closely that thinking aligns with the real-world domain you’re modeling.
So next time you see a class called StudyAggregateRoot
, ask yourself:
What makes this an aggregate? What invariant is it protecting? What part of the domain logic does this model embody?
If you can answer that clearly, you’re on the right path.
If not, maybe it’s time to put the patterns down and go talk to someone who actually knows what a "Study" does.
Top comments (0)