Skip to content
Leo Jung
Go back

[DDD Intro #29] DDD adoption checklist

Edit page

DDD is a powerful approach, but it is not needed for every problem. It can greatly help complex domains, but applying it excessively to a simple CRUD system can only increase cost.

So before adopting DDD, we must ask first. Do we really need DDD? If we do, where should we apply it? Is the team ready to talk with domain experts? What is the biggest problem in the current code?

This article is a checklist for deciding whether to adopt DDD. Rather than a list that gives answers, it is closer to a set of questions for the team to discuss together.

1. Is the domain complex enough?

DDD is a method for handling complex domains. So first, we need to see where complexity exists.

Are there many state transitions?
Do business rules change often?
Are there many exception policies?
Does the same feature behave differently depending on customer type or situation?
Are there many cases where operators make manual judgments?

For example, if renewal, expiration, cancellation, refund, plan change, free trial, and grace period are complexly intertwined in a subscription service, DDD is worth considering.

On the other hand, if it is notice management that simply stores a title and body, deep DDD modeling may not be necessary.

What matters is distinguishing complex areas from simple areas.

2. What is the Core Domain?

Not every area needs the same level of design. If adopting DDD, first find the Core Domain.

Where does our service's competitiveness come from?
Which area has the greatest business impact if designed poorly?
Which policy changes most often?
Which feature requires the most conversation with domain experts?

If the Core Domain is unclear, DDD spreads everywhere. Then even simple features become heavy, and the team feels DDD as a burdensome procedure.

DDD is more about focused application than whole-system application.

3. Can we talk with domain experts?

DDD is not a design activity for developers alone. It requires conversation with domain experts.

Is there someone who can explain domain rules?
Is there a channel where developers can ask domain questions?
Can we hear real operational knowledge beyond requirement documents?
Is there time to discuss and organize terminology differences?

If developers model alone without domain experts, the model becomes guesswork. Of course, an ideal domain expert is not always available. In that case, we must find domain knowledge through operators, planners, customer support, data analysts, existing code, and operational documents.

What matters is the attitude of continuously exploring domain knowledge outside the code.

4. Is the same word used with different meanings?

One signal that Bounded Context is needed is when the same word is used differently by context.

Is a member the same as a user in the authentication system?
Is a customer a buyer, subscriber, or billing target?
Is a product a displayed product, ordered product, or settlement product?
Is subscription cancellation the same as refund, or different?
Are payment cancellation and refund the same word?

If these questions are hard to answer, model boundaries should be considered. If we try to express everything with one common model, the model grows bloated over time.

An important starting point of DDD adoption is discovering terminology collisions.

5. Where are domain rules in the current code?

Open the code and check where domain rules are.

Inside Entity?
Inside Application Service?
Inside Controller?
Hidden in Repository queries?
Duplicated in the frontend?
Only in operation manuals or people's memory?

If rules are scattered across many places, DDD can help. Domain objects, Policy, Domain Service, and tests can gather rules explicitly.

Code like this is especially a warning sign:

if (status == "A" && paymentStatus == "P" && type != "TRIAL") {
    // ...
}

If there is no name for what this condition means, a domain concept is hidden inside the code.

6. Are transaction boundaries unclear?

In DDD, Aggregate is a consistency boundary. If it is unclear what must be protected inside one transaction in the current system, Aggregate design may be needed.

Which objects must always change together?
Which rules must not be broken even briefly?
Which follow-up processing can happen later?
Is the model becoming too large because everything is placed in one transaction?

If transactions are too large, performance and changeability suffer. Conversely, if rules that must be protected together are distributed, data breaks easily.

DDD helps distinguish kinds of consistency.

7. Can the team bear the design cost?

DDD is not free. It takes time to align terminology, refine models, split boundaries, and write tests.

Can the team review domain models together?
Can domain language be discussed in code review?
Can design decisions be documented or shared?
Can the team spend time on the core domain even under short schedules?

To do DDD properly, the team’s learning and collaboration are needed. If only one or two people understand DDD and everyone else only follows patterns, failure is likely.

It is better to start small. Modeling one use case in the Core Domain, writing tests, and aligning language with the team is realistic.

8. Are we trying to apply DDD everywhere?

The most common failure in DDD adoption is over-application.

Creating Aggregates even for simple CRUD.
Publishing Domain Events for every state change.
Creating complex Ports and Adapters for every external call.
Turning every conditional into a Specification.

This makes DDD a heavy structure. DDD is a way to focus design energy on important domains. Simple areas should be allowed to have simple structures.

A good checklist should include not only “where to apply it,” but also “where not to apply it.”

9. Can we start gradually?

DDD is better introduced gradually than all at once.

Separate one complex conditional into a Policy.
Change one primitive value into a Value Object.
Change one setter-based state change into domain behavior.
Write a domain test for one core use case.
Hide one external API model behind an ACL.

Small successes build the team’s confidence. If we try to change the whole architecture from the start, resistance is high and failure cost is large.

DDD is closer to a continuous model refinement process than an adoption project.

Closing

Whether to adopt DDD should not be decided by trends or technical preference. We need to look together at domain complexity, business value, the team’s collaboration style, and problems in the current code.

Good questions are:

Do we have a complex domain?
Is that complexity scattering inside the code?
Can we create a shared language with domain experts?
Where is the Core Domain?
Where do we not need DDD?
Can we start small?

If we can answer these questions, DDD becomes a much more realistic choice. Conversely, if we start creating Entity, Aggregate, and Repository without these questions, DDD easily becomes a formal structure.

DDD adoption starts not from applying patterns, but from questions. Good questions create good models.


Edit page
Share this post:

Previous Post
[DDD Intro #30] My understanding of DDD: Good design starts from good questions
Next Post
[DDD Intro #28] Modular Monolith: What to think about before microservices