Eric Evans, the creator of Domain-Driven Design, has a message that might surprise you: your perfectionism is undermining your software design. In one of his most-watched presentations from DDD Europe 2019, Evans cuts through the mystique of DDD to reveal a pragmatic truth: the goal isn't to build perfect models, it's to build software that does an important job effectively.
The Perfectionist Trap
"The core goal of software development is to create software that performs an important job effectively," Evans states plainly. Yet many teams get stuck obsessing over the perfect model, the perfect abstraction, the perfect domain representation.
This perfectionist tendency creates a paradox: the pursuit of ideal design often produces worse outcomes than accepting "good enough" solutions that actually solve real problems.
Evans challenges a fundamental assumption: "The usefulness of models or particular modelling styles should not be taken for granted." Just because you have a model doesn't mean it's helping. The advantage comes from having a model well-suited to the specific problems within your domain and context.
Two Perspectives, One Codebase
Evans introduces a powerful technique for evaluating software: constantly shifting between two perspectives.
The Software Engineer Perspective:
- Clean code principles
- Separation of concerns
- Maintainability and technical quality
The Domain Expert Perspective:
- Can you explain this code to shipping experts?
- Does the software language match how domain experts think?
- Would a non-technical stakeholder understand what's happening?
Most teams optimize for one perspective and ignore the other. The magic of DDD is in the tension between both, building software that is both technically sound and deeply aligned with how the business actually works.
The Container Shipping Example: Models in Action
To make these ideas concrete, Evans walks through a real-world scenario: software for intermodal container shipping logistics.
The use case: A customer wants to ship a container from Hong Kong to Dallas, Texas. A clerk inputs the origin and destination, the system produces a routing plan (which ships, which trains, what timings), and the booking is confirmed.
The existing system is straightforward:
- A Cargo object holds origin and destination data
- A Routing service computes the route
- The result gets stored in a database
Simple. Clear. Easy to explain to stakeholders.
The problem? When cargo shows up with disconnected itineraries, unloaded in Long Beach but somehow reloaded in Sacramento, 400 miles away, nobody notices until cargo goes missing. The database has integrity constraints, but the software doesn't make domain problems visible or solvable.
The Language Gap That Kills Projects
Here's where it gets interesting. When Evans explains routing to domain experts, he naturally talks about "stops", the ports where cargo is loaded and unloaded. But look at the code: the term "stops" doesn't exist anywhere.
The software language and the domain language have diverged.
This gap creates friction everywhere:
- Developers and domain experts talk past each other
- Business logic gets hidden in technical plumbing
- Problems that should be obvious become invisible
- New features require extensive translation effort
The solution isn't just better documentation or comments, it's building the domain language directly into the code itself.
Generate Multiple Models (Yes, Really)
Evans advocates for something most teams find uncomfortable: generating multiple competing models before choosing one.
For the cargo itinerary problem, he proposes two fundamentally different approaches:
Model 1: Stops
- A sequence of locations where cargo is loaded or unloaded
- Emphasizes port operations and activities
- Natural for thinking about what happens at each location
Model 2: Legs
- A sequence of journey segments between stops
- Emphasizes the transport segments (ship legs, train legs)
- Natural for thinking about routing and transportation
Most teams would pick the first reasonable idea and run with it. Evans pushes back: "Generate at least three alternatives. Shift your thinking from picking one to exploring a broad design space."
Why? Because the first model that works often isn't the best fit for the problems you'll actually encounter.
The Mercator Map: A Perfect Model of Imperfection
To illustrate what models really are, Evans uses the Mercator projection, the familiar world map that makes Greenland look as large as Africa (despite being 14 times smaller).
Is the Mercator map wrong? Only if you're measuring land area. For navigation, it's brilliant, it preserves compass headings, making it possible to draw a straight line between two points and sail that bearing.
The map embodies specific assumptions (Earth as sphere, only surface geography matters) and makes deliberate trade-offs (distortion for navigational utility).
Key insight: Models are not realistic representations of reality. They're purpose-driven abstractions. A model that tries to capture everything captures nothing useful.
Scenario-Driven Model Selection
How do you choose between competing models? Evans recommends testing them against real domain scenarios.
Scenario 1: Initial booking Both "stops" and "legs" handle this equally well.
Scenario 2: Mid-transit destination change Now the differences emerge:
- Legs model: Simply cancel or replace specific leg segments. Natural and clean.
- Stops model: Must manipulate loading/unloading components at each stop. More complex.
For this scenario, the "legs" model proves superior. But introduce a new requirement, generating purchase orders for port operations, and suddenly the "stops" model might shine.
Model choice is problem-dependent. Different domain problems favour different models.
When Models Multiply: Bounded Contexts
What happens when your domain grows and different parts favour different models?
Evans introduces bounded contexts: separate conceptual areas within a larger system, each with its own model and ubiquitous language.
Three evolution options when models diverge:
- Modify existing model - Accept more complexity to handle new problems
- Create separate bounded contexts - Different models for routing (legs) vs port operations (stops), with transformations between them
- Force one model everywhere - Cram everything into a single model, increasing complexity
Option 3 is what happens by default if you don't choose consciously. It's the path of least resistance and often the worst long-term choice.
Domain Complexity vs Technical Complexity
Not every system needs DDD. Evans distinguishes between:
Technical complexity - Early Twitter's scaling challenges were primarily technical, not domain-driven
Domain complexity - Shipping logistics, financial systems, healthcare, where business rules and domain knowledge dominate
"Domain-Driven Design is especially valuable when domain complexity is the main challenge," Evans notes. "Poor modelling can lead to software complexity exceeding the inherent domain complexity, which is undesirable."
If your biggest challenge is handling 50,000 requests per second, DDD might not be your primary tool. If your biggest challenge is representing complex business processes that domain experts barely understand themselves, DDD becomes essential.
The Collaborative Modelling Process
Evans shares practical advice for modelling sessions:
Keep them short: Around 90 minutes to maintain creativity and energy
Quantity over quality initially: Generate deliberately bad ideas to explore the design space
Psychological safety: Team members must feel safe proposing flawed ideas without judgment
Minimal documentation: Only record what's valuable for future reference
Transparent decisions: Include stakeholders impacted by the decision (project managers, other teams) in the selection process
Don't settle on the first good idea: It stifles innovation and exploration
The Real Goal: Fit, Not Perfection
Evans closes with a critical insight that frames everything:
"Having a model is not inherently advantageous. The advantage comes from having a model well-suited to the specific problems within the domain and context."
A misaligned model, no matter how elegant or technically sophisticated, hinders progress. A simple model that fits the problem enables progress.
The question isn't "Is this a good model?" but rather "Does this model help us solve the problems we're actually facing?"
Learn More
This article captures the spirit of Eric Evans' approach, but there's much more nuance and depth in the full presentation.
Watch the complete talk: Domain-Driven Design: The Good Parts - One of the most-viewed DDD presentations, packed with practical insights.
See Eric Evans live: Join him at DDD Europe 2026 where the creator of Domain-Driven Design will share his latest thinking with the DDD community.
Start your Domain-Driven Design journey with a tactical workshop.
Domain-Driven Design isn't about perfection. It's about building software where the code speaks the language of the business, where models fit the problems they're meant to solve, and where domain experts and developers can actually understand each other. Sometimes the best model is the one you almost didn't consider.