Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Models a business in its own language. Use when the domain has real business rules to capture.
.claude/skills/athola-architecture-paradigm-domain-driven/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-13 | ✗→✓ | ▲ Improved | 15% | 0% |
| case-01 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 15% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 87% | 0% |
Design for the future, build for now.
DDD is modeling a business in the business's own language. The goal is not to avoid structure. It is to avoid structure you cannot back out of, and to defer structure you do not yet need.
Ubiquitous language, bounded contexts, and a model built by talking to the people who do the work. The measure of a domain model is whether a person in the business would recognize their own job in it.
Clean Architecture. Mandatory layering. A mapper between every tier. A count of design patterns applied before the first line of business logic is written.
These are DDD-adjacent choices. Each has its own justification, and none of them is entailed by DDD. Wanting to decouple an API from the domain is a good reason to add a DTO. "This is what DDD requires" is not, because it does not.
The building blocks are not the point, and this is not the repo's opinion. Evans said so himself, ten years after the book, about the book:
> "things like the entities and value objects ..] People] come away > thinking that that's really the core of DDD, whereas, in fact, it's > really not."
> "I really think that the way I arranged the book gives people the wrong > emphasis, so that's the biggest part of what I do is rearrange those > things."
Source: SE-Radio Episode 226, "Eric Evans on Domain-Driven Design at 10 Years" (video). Quotes as transcribed by The Core of Domain-Driven Design, which also cites his DDD Europe 2016 keynote criticizing the "over-emphasis on building blocks."
What the core actually is: discovering subdomains and drawing bounded contexts, in language the business already speaks. Entities, value objects, and aggregates are how a model reaches code once it exists. They are the translation, not the thing being translated.
Read the rest of this skill in that light. Every mechanism below is optional machinery serving a model you found by talking to people.
Once a domain exists, create the data store and one concrete data object. Pass that object from the repository into the business layer. At the start of a project, pass it out to the view as well.
That is a legitimate starting state, not technical debt. One object moving through every layer is the cheapest thing that can work, and it is the shape the divergence protocol below is designed to split.
The DTO arrives at the moment of divergence, not in anticipation of it.
Trigger: the view's response shape must hold for contract reasons while the domain model needs to change.
Move: the old data object becomes the view DTO. The new domain object gains a translation into it. Where fields differ, a copy constructor maps them, in either direction as needed.
That is the whole mechanism. It works because the starting state (one shared object) is the same shape as the ending state's DTO, so the split costs one rename and one translation function. This is why "we might need a DTO later" is not a reason to build one now: later is cheap.
Ordered by cost:
everywhere, use the same object.
fixed field set.
object, JSON representation). Each context adds its own fields on top of a shared core. This reduces duplication when several contexts genuinely share that core.
Option 3 carries a cost worth stating plainly: inheritance couples the layers. Changing the base changes every context at once, which is the opposite of the flexibility the divergence protocol buys. It also feeds straight into the boundary hazard below. Reach for it when duplication is the larger present pain, and reach for it knowing what it trades away.
Do not reuse a data type across a network or other IO boundary without validating that you are not sharing something you should not.
This is the one non-negotiable constraint in this skill. Everything else here can be deferred, dropped, or added later. This cannot.
Option 3 is where it bites hardest: a field added to a shared base class appears silently in every serialized representation that inherits it, including the one crossing the wire. The convenience is real and so is the leak.
When two or more systems exchange commands over a network and do not deploy atomically, a versioned request DTO lets you introduce a new shape while continuing to serve the old one, and migrate the systems one at a time. Without it, any change to the command shape requires every system to update simultaneously, which fails the moment one update fails or one release waits on an app store, an IT department, or another team.
That is a deployment constraint, not a DDD principle. Name it as such when you justify the DTO, so the next reader knows which force put it there and when it can go.
Never in one pass. A refactor that tries to do every layer at once does not land. Per domain, in order:
Then repeat for the next domain. Keep the implementation simple until a need for more appears.
the terms they use, and use exactly those terms in code.
and another starts. A term meaning two things is two contexts.
the model actually pull apart, not before.
.claude/rules/ceremony-requires-need.md and theceremony-audit lens in Skill(pensive:architecture-review). A mapper whose fields are all 1:1 copies is a mapper with no job.
lives in a service, the model is a schema with a new name. Move the rules onto the objects that own them, or accept that this domain does not need DDD.
as a leak risk, not just a duplication fix.
These vocabulary items name the concrete tools and abstractions that show up when the paradigm is implemented. They are not required dependencies and they are not part of the skill's tools: frontmatter (which is reserved for Claude Code tool restrictions). Use this list to disambiguate during architecture discussions.
ubiquitous-language-glossary: the term list the business and the codeboth use, maintained as a first-class artifact
context-map: names each bounded context and the relationships betweenthem, including where one term changes meaning
copy-constructor: the translation introduced at the moment ofdivergence, mapping fields between a domain object and its view DTO
without translation.
copy, or a documented contract reason to exist.
what they expose.
which layer it has reached.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | pass→pass | 14,989 | 6,909 | -54% | 1 | 1 | 0% | 2,076 | 3,067 | +48% | 0 | 0 | — |
case-13 | fail→pass | 13,859 | 2,158 | -84% | 1 | 1 | 0% | 2,094 | 2,409 | +15% | 0 | 0 | — |
case-01 | fail→pass | 29,582 | 13,043 | -56% | 1 | 1 | 0% | 4,499 | 4,105 | -9% | 0 | 0 | — |
case-02 | fail→pass | 21,824 | 10,278 | -53% | 1 | 1 | 0% | 3,227 | 3,702 | +15% | 0 | 0 | — |
case-03 | fail→pass | 20,605 | 14,799 | -28% | 1 | 1 | 0% | 3,220 | 4,330 | +34% | 0 | 0 | — |
case-04 | pass→pass | 15,594 | 8,169 | -48% | 1 | 1 | 0% | 2,197 | 3,173 | +44% | 0 | 0 | — |
case-05 | pass→pass | 18,046 | 11,290 | -37% | 1 | 1 | 0% | 2,808 | 3,841 | +37% | 0 | 0 | — |
case-06 | pass→pass | 19,976 | 15,355 | -23% | 1 | 1 | 0% | 3,011 | 4,404 | +46% | 0 | 0 | — |
case-08 | pass→pass | 8,639 | 1,817 | -79% | 1 | 1 | 0% | 1,277 | 2,351 | +84% | 0 | 0 | — |
case-09 | fail→pass | 9,529 | 4,562 | -52% | 1 | 1 | 0% | 1,474 | 2,761 | +87% | 0 | 0 | — |
case-10 | pass→pass | 13,781 | 3,995 | -71% | 1 | 1 | 0% | 1,961 | 2,653 | +35% | 0 | 0 | — |
case-11 | pass→pass | 17,242 | 8,675 | -50% | 1 | 1 | 0% | 2,420 | 3,306 | +37% | 0 | 0 | — |
case-12 | pass→pass | 14,687 | 2,699 | -82% | 1 | 1 | 0% | 2,112 | 2,507 | +19% | 0 | 0 | — |
case-14 | pass→pass | 14,924 | 9,555 | -36% | 1 | 1 | 0% | 2,322 | 3,492 | +50% | 0 | 0 | — |
case-15 | pass→pass | 10,248 | 3,126 | -69% | 1 | 1 | 0% | 1,380 | 2,588 | +88% | 0 | 0 | — |
case-16 | pass→pass | 7,663 | 2,540 | -67% | 1 | 1 | 0% | 1,165 | 2,452 | +110% | 0 | 0 | — |
case-17 | pass→pass | 11,631 | 3,341 | -71% | 1 | 1 | 0% | 1,647 | 2,588 | +57% | 0 | 0 | — |
case-18 | pass→pass | 8,271 | 2,010 | -76% | 1 | 1 | 0% | 1,242 | 2,365 | +90% | 0 | 0 | — |
case-19 | fail→pass | 10,848 | 2,632 | -76% | 1 | 1 | 0% | 1,578 | 2,513 | +59% | 0 | 0 | — |
case-20 | pass→pass | 13,249 | 4,178 | -68% | 1 | 1 | 0% | 2,028 | 2,762 | +36% | 0 | 0 | — |
case-21 | pass→pass | 9,833 | 1,843 | -81% | 1 | 1 | 0% | 1,498 | 2,370 | +58% | 0 | 0 | — |
case-22 | fail→pass | 11,238 | 3,530 | -69% | 1 | 1 | 0% | 1,703 | 2,607 | +53% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.