If You Apply DDD to DDD, You Won't Get DDD¶
Domain-Driven Design (DDD) promises better software through a focus on the business domain and a shared understanding between developers and domain experts. That's the essence, distilled to one sentence. But if you actually apply this principle to DDD itself – asking what the domain is, what matters, what can be discarded – you won't end up with what we call "DDD" today. You'll end up with something much simpler.
So why has DDD, after more than two decades, never escaped its niche? Why do so many developers feel overwhelmed by it, confused by it, or think they're not smart enough for it? The answer is uncomfortable but clear: DDD fails at its own claim.
The Problem: DDD Scares People Away¶
DDD has been around since 2003. Eric Evans' Blue Book ("Domain-Driven Design: Tackling Complexity in the Heart of Software") is considered a classic, and the ideas it contains are powerful. Yet DDD remains confined to a relatively small community of practitioners. It hasn't become mainstream. It hasn't revolutionized how most teams build software. And one major reason is this: we lose people before they even understand the core idea.
Instead of meeting developers where they are, we hit them with a wall of theory. Aggregates. Bounded Contexts. Value Objects. Entities. Repositories. Anti-Corruption Layers. Ubiquitous Language. Strategic Design. Tactical Design. The terminology alone is intimidating. The concepts are abstract. The examples often remain academic. And by the time someone has waded through all of that, they're either exhausted or convinced that DDD is only for enterprise architects with decades of experience.
This isn't an accident. DDD has been academized. It's been turned into a framework, a methodology, a certification path. It's been wrapped in jargon and buried under layers of pattern catalogs. What started as a simple, human-centered idea – understand the domain, speak the language of the business – has become something that feels inaccessible to most developers.
And that's the paradox: DDD is supposed to make software development simpler and more aligned with reality. But the way we teach it, the way we talk about it, the way we practice it – all of that makes it harder.
Intention vs. Implementation: A Familiar Story¶
This isn't a new problem. The same thing happened with the Gang of Four design patterns.
Take the Singleton pattern. The intention is simple: ensure that a class has exactly one instance. That's it. That's the problem the pattern solves. But what did most developers learn? They learned the implementation: a private constructor and a static getInstance() method. They memorized the code. They applied it mechanically. And many of them never understood that the implementation is just one way to achieve the intention. The implementation became the pattern itself.
The same thing has happened with DDD. The intention is clear: build better software by focusing on the business domain and developing a shared language with domain experts. But what do developers learn? They learn the implementation: a long list of patterns. Aggregates. Bounded Contexts. Value Objects. Entities. Repositories. And just like with Singleton, many developers start to believe that applying these patterns is what DDD is. They treat it like a checklist.
"Do we have Aggregates? Check. Do we have Value Objects? Check. Do we have Bounded Contexts? Check."
But that's not DDD. That's pattern theater. It's form without substance. It's like running Daily Standups, Sprints, and Retrospectives and calling yourself agile – even though nothing about your team's culture, communication, or decision-making has changed. You're doing the rituals, but you're missing the point.
The Great Escape: Hiding Behind Patterns¶
Here's the uncomfortable truth: DDD is fundamentally non-technical. What it really demands from you is this:
- Step out of your comfort zone.
- Talk to domain experts – not just to gather requirements, but to truly understand their world.
- Listen. Ask questions. Sit with uncertainty. Admit when you don't understand something.
- Develop a shared language, iteratively and collaboratively.
This is hard work. It's human work. It's uncomfortable work. It requires humility, patience, and communication skills that many developers – myself included – haven't been trained in. It's much easier to stay in the technical realm, where things are predictable and controllable.
And here's the trap: the patterns give you a perfect hiding place.
Instead of talking to people, you can discuss whether something should be an Aggregate or an Entity. Instead of understanding the domain, you can draw Bounded Context diagrams. Instead of asking domain experts "How do you call this?" you can ask your fellow developers "Is this a Value Object?" You feel productive. You're creating structure, drawing diagrams, applying patterns. But the actual work – the hard, human, domain-focused work – gets pushed aside.
This is why so many DDD projects end up looking technically sophisticated but feel disconnected from the business. The code is full of the right patterns, but it doesn't speak the language of the domain. The architecture is clean, but the developers still don't really understand what the software is supposed to do or why.
"I'm Too Stupid for DDD"¶
For years, I thought I was too stupid for DDD.
I read the books. I watched the talks. I studied the diagrams. The big picture made sense – focus on the domain, build a shared understanding – but when it came to the details, I got lost. Aggregates, Bounded Contexts, Anti-Corruption Layers. I understood them in theory, but I never felt confident applying them. I thought everyone else just "got it" and I didn't.
Then I realized: the problem wasn't me. The problem was the way DDD is taught.
DDD has been made unnecessarily complicated. It's been dressed up in academic language, buried under layers of abstraction, and presented as if it requires a PhD in software architecture to understand. But that's not what DDD is. DDD isn't complicated. We made it complicated.
If you've ever felt the same way – if you've ever thought you're not smart enough for DDD, or that it's only for certain kinds of projects, or that it's just too abstract to be useful – you're not alone. And you're not the problem.
What DDD Is Really About¶
Let's strip away the complexity and get to the essence. Here's DDD in one sentence:
Build better software by understanding the business domain and speaking a shared language with the people who work in it.
That's it. Everything else – all the patterns, all the diagrams, all the terminology – is secondary. The patterns are tools. They can help you express the domain more clearly in code. But they're not the goal. The goal is understanding.
So what does that look like in practice?
First, talk to people, not diagrams. The most important question you can ask isn't "Is this an Entity or a Value Object?" It's "What do you call this?" Spend time with domain experts. Listen to how they describe their work. Pay attention to the words they use, the distinctions they make, the things they care about. That's where the shared language comes from – not from UML diagrams, but from real conversations.
Second, use the language of the domain, not the language of technology. If the domain experts talk about customers, guests, and users as three different concepts, then your code should reflect that. Don't collapse them all into a single User class just because it's simpler. Don't call something a UserEntity when the business calls it a Customer. The precision of the language matters. It's not pedantic – it's the core of DDD.
Third, name things exactly. Is it "cancel" or "refund"? Is it an "invoice" or a "receipt"? Is it "return" or "revoke"? These aren't trivial distinctions. They represent different business processes, different rules, different meanings. If you get the names wrong, you've already lost alignment with the domain.
Fourth, move away from CRUD. Create, Read, Update, Delete – these are technical operations, not business processes. They don't capture what's actually happening in the domain. Instead, think in terms of verbs that come from the business: confirmOrder(), cancelOrder(), changeDeliveryAddress(). These names tell you what the system does and why.
Finally, remember: patterns are tools, not goals. If an Aggregate pattern helps you express a business concept more clearly, use it. If it doesn't, leave it out. Let the domain guide your structure, not pattern catalogs. The patterns exist to serve the domain, not the other way around.
Why Event Sourcing Feels Natural¶
Here's something I've noticed over the years: people understand events intuitively.
Events are how we naturally think about the world. We tell stories as sequences of things that happened. We describe our day in events: I woke up, I had breakfast, I went to work, I attended a meeting. When we recount history, we talk about events: the wall fell, the treaty was signed, the discovery was made. This isn't a technical abstraction. It's how humans process and communicate information.
Let me give you an example. Imagine you're telling the story of Little Red Riding Hood. You wouldn't do it like this:
UPDATE LittleRedRidingHood SET location = 'forest'
UPDATE Wolf SET location = 'forest'
UPDATE LittleRedRidingHood SET emotion = 'frightened'
DELETE Grandmother
UPDATE Wolf SET disguise = 'Grandmother'
That's absurd. It strips away all the meaning, all the causality, all the narrative. You'd tell it as a sequence of events:
LittleRedRidingHoodEnteredTheForest
LittleRedRidingHoodMetTheWolf
WolfWentToGrandmothersHouse
WolfDevauredGrandmother
WolfDisguisedAsGrandmother
This is how stories work. It's how we understand what happened and why. And it's exactly how event sourcing works.
Event sourcing doesn't ask "What is the current state?" It asks "What happened?" It stores a chronological log of facts – things that occurred, in the past, immutable and undeniable. And from that log, you can reconstruct the current state, replay history, understand causality, and build a complete picture of what led to where you are now.
Event Sourcing as a Lightweight Path to DDD¶
Event sourcing isn't just a way to store data. It's also a surprisingly effective, lightweight entry point into the world of DDD. Why? Because it naturally pushes you in the right direction.
First, it forces you to think in verbs, not CRUD. Events have names like OrderPlaced, PaymentReceived, ItemShipped. Not createOrder, updatePayment, deleteItem. You can't fall back on generic CRUD operations. You have to describe what actually happened in the business. This immediately brings you closer to the domain language.
Second, organizing events into subjects is half the Aggregate discussion. Which events belong together? All the events for a specific order go under /orders/42. All the events for a specific customer might go under /customers/23. Or maybe you structure it differently: /customers/23/orders/42. The way you group events reflects the structure of the domain. You're doing the work of defining Aggregates – but you're doing it concretely, by deciding which events belong together, not by debating abstract concepts.
Third, deciding which service handles which events is the Bounded Context discussion. Should the order service handle PaymentReceived, or should that be the billing service? What belongs in inventory versus fulfillment? These are Bounded Context questions. But you're not drawing diagrams. You're making concrete decisions about which part of your system is responsible for which events. The domain naturally emerges from these decisions.
Finally, events are self-explanatory. You don't need to understand Aggregates, Entities, or Value Objects to know what CustomerRegistered means. You don't need a degree in DDD to figure out what BookBorrowed represents. Events speak the language of the business. They're accessible. They're concrete. They're immediately understandable.
Let's look at a simple example from a library system. Instead of thinking about whether a book is an Entity or an Aggregate, you start by asking: what can happen with a book?
BookAcquired – the library gets a new book
BookBorrowed – someone borrows it
BookReturned – they bring it back
LateFeeCharged – they returned it late
BookRemoved – the library discards it
These events tell the story. They capture the business process. And if you organize them by subject – say, /books/42 for book number 42 – you've just defined what in DDD terms would be called an Aggregate. You didn't need the theory. You just asked: what happens, and what belongs together?
A Call for Pragmatic DDD¶
Maybe what we need isn't more DDD. Maybe what we need is Pragmatic DDD.
Strip away the academic language. Stop treating patterns as the goal. Stop overwhelming people with theory before they've even written a line of code. Get back to the essence: focus on the domain, speak the language of the business, build a shared understanding.
If you want to learn DDD, start here:
- Forget the patterns for now. Learn to have good conversations with domain experts.
- Learn to listen carefully, ask the right questions, and sit with uncertainty.
- Learn to think in events: what happened, and why?
- Let the domain guide your code, not the other way around.
If you're already practicing DDD, ask yourself honestly:
- Am I hiding behind patterns instead of doing the hard work of understanding the domain?
- How much time do I spend with domain experts versus how much time I spend drawing diagrams?
- Does my code speak the language of the business, or does it speak the language of technology?
- Am I using CRUD, or am I using events and domain verbs?
DDD was never meant to be complicated. We made it complicated. If we take DDD seriously – if we apply its own principles to itself – we have to admit: we've drifted from the core. We've built layers of abstraction that obscure the simplicity underneath.
Event sourcing can help. It's concrete. It's intuitive. It aligns naturally with how people think. And it pushes you, almost effortlessly, toward the practices that DDD has always been about: understanding what happened, naming it precisely, and speaking the language of the domain.
If you're curious about event sourcing and want to see how it can guide you toward better domain modeling without the overhead, start with Introduction to Event Sourcing. You might find that the path to DDD is simpler than you thought.