ddd-master

v2026.09.24

Assess DDD fit; discover domains with EventStorming, define language and bounded contexts, and design aggregates, value objects, events, and repositories. Excludes architecture-only audits, product specs, and CQRS/Event Sourcing catalogs.

GitHub
Install command
npx skhub add pedronauck/ddd-master
Markdown
SKILL.md

DDD Master

Define or revise a domain model from its language, boundaries, and invariants. Assess DDD fit before scaffolding a new model; reuse accepted decisions for established models.

Use the branch covering the changed model or decision. Reuse established language, context maps, and timelines. Read the relevant sections and their contract dependencies; a complete reference read is needed only when the contract is inseparable.

Bundled Path Rule

Resolve bundled files relative to the directory that holds this SKILL.md. A path written references/<name> expands to <ddd-master-dir>/references/<name>.

Branches

When the task involves…Relevant sections
Refusing DDD, anemic models, transaction script, slogan folders, CRUD, or legacy rewritereferences/when-not.md: Three verdicts, Essential complexity, or Legacy
EventStorming, event timelines, or grasping what happens before contexts existreferences/discovery.md: Skip / swap gate, Family of formats, What the agent does vs fakes
Ubiquitous language, subdomains, bounded contexts, context map, or context relationshipsreferences/strategic.md: Ubiquitous language, Context map, Relationship decision tree
Aggregates, value objects, domain events, repositories, factories, or invariantsreferences/tactical.md: Classification tests, Consistency boundary, and the affected building block
Rule density, repository FAQ, or Branas/Elemar practitioner checksreferences/practitioner.md: Density, Small aggregates, or Repository FAQ
CQRS-by-default, copying a "DDD" repo, LLM-generated aggregates, or model/code driftreferences/pitfalls.md: the diagnosed modeling or generation pitfall

For a new or redesigned model, work through the relevant discovery, strategic, and tactical decisions. A narrow change inside an established context needs only its affected invariants and consumers. Downgrade-to-layers can use architectural-analysis when a structural audit is requested.

Floor

  1. Ground new context boundaries in the organization's knowledge areas; reuse the established map for local changes.
  2. Treat subdomain, bounded context, and deployable as three objects.
  3. One transaction updates one aggregate; other aggregates appear as identities.
  4. Place every invariant on the root, value object, or domain service; repository methods only load, save, and search.
  5. Register a past-tense domain event after a successful command; publish it after persist.
  6. Treat a language change as a model change.

Step 1: Verdict

Classify new or redesigned models before scaffolding. Use the questions below where they affect the decision; a focused question or local fix needs only its relevant rationale.

  1. Tag essential complexity (multi-step invariants that change together) or write "CRUD + syntax only."
  2. Tag the subdomain core, supporting, or generic.
  3. Flag slogan DDD: Evans vocabulary or layer folders without a collaboratively evolved model of rules.
  4. If objects are data bags and services own the rules, name transaction script (or operations-over-records). Keep the DDD label off that design.
  5. If the change sits inside a ball of mud, pick Bubble, Autonomous Bubble, or Open-host-over-ACL — when the request is a legacy rewrite, read the Legacy section of references/when-not.md before choosing.
  6. Tag each rule syntax, semantic, or production. Syntax may stay in the UI; semantic and production rules earn a model owner only on Proceed.

Record Refuse, Downgrade, or Proceed.

Done when: the approach and consequential reasons are clear. Record only classifications that affect the model; Refuse and Downgrade do not scaffold unnecessary aggregate or repository types.

Step 2: Grasp the domain

Run when the verdict is Proceed and no trusted event timeline exists. When the user asked for EventStorming or "what happens," read the matching format and facilitation sections of references/discovery.md.

  1. List who knows the questions (code, APIs, logs) and who knows the answers (named humans). Absent answerers become a hotspot.
  2. Hang past-tense domain events on one unbounded timeline. Prefer sentence names.
  3. Sequence in time; walk backward from the end once; mark gaps as red hotspots.
  4. Place a present-tense command and an actor immediately before each event, or a hotspot when the cause is unknown.
  5. Dual-visualise disagreements. Ask money path, success metric, and missing-role questions; leave a hotspot when the answer is unknown.
  6. Stop after events, commands, and hotspots unless the user asked for software-design depth. Yellow notes are aggregate candidates — Step 4 owns their rules.
  7. Carve loosely coupled subdomain cuts and hand relationship types to Step 3.

Skip the workshop tool when a recent EventStorm, Domain Storytelling, or Example Mapping already exists — keep the timeline artifact and continue at the carve. Reopen discovery only for gaps relevant to the requested change.

Done when: a sequenced past-tense timeline exists; every event has a command/actor or a hotspot; the roster or the gap is written.

Step 3: Strategic design

Run when creating or changing context boundaries or language. When drawing contexts, locking language, or mapping relationships, read the relevant language or context-map sections of references/strategic.md.

  1. Classify every named capability core / supporting / generic. Generic lists a buy-or-reuse candidate.
  2. Hunt polysemes (Customer, Order, Account). Split the term across contexts or give it one meaning inside a named context.
  3. Lock ubiquitous language per emerging context: glossary, one walked scenario, code names that match.
  4. Design bounded contexts. Default: one core + one context. Split when language, purpose, owner, or use diverges. Name each context (the name enters the language).
  5. Draw a context map of the surroundings. Each edge states direction (upstream/downstream, mutually dependent, or free) and one primary pattern. When choosing ACL, OHS, conformist, partnership, shared kernel, customer/supplier, published language, separate ways, or big ball of mud, use the Relationship decision tree in references/strategic.md.
  6. Fill required canvas cells for each context the agent owns: name, purpose, UL terms, inbound or outbound messages.

Done when: every named area has a subdomain type; every in-scope context has name, purpose, and boundary; every neighboring edge has direction + pattern; required canvas cells are non-empty.

Step 4: Design one aggregate

Run only for a bounded context labeled Domain Model. When designing building blocks, read the affected building-block sections of references/tactical.md, including consistency and publication dependencies when applicable. When judging rule density or a repository FAQ, read Density or Repository FAQ in references/practitioner.md.

  1. Name the aggregate and its lifespan (billing period, sprint, or process-scoped).
  2. List true invariants — rules that must hold after every successful command. Drop relationship-only and "cannot delete X if Y exists" false invariants.
  3. Classify each concept: identity through change → entity; replaceable / equal by attributes → value object; own invariants and lifecycle → other aggregate referenced by id.
  4. Draw the consistency boundary. Each insider names the invariant it shares with the root; each outsider is an id.
  5. Choose the root and the write API. Commands are imperative; events are past tense. Pair them.
  6. Place spanning invariants on the root. Local VO/entity rules stay local.
  7. Load foreign aggregates in the application (or domain) service before the command. The aggregate opens no repository.
  8. Label each cross-aggregate rule transactional or eventual and name whose job it is. Eventual: register a domain event; update the other aggregate in a later transaction.
  9. Note size and conflict (command rate × concurrent clients; graph/event growth × lifetime). Split when insiders share no invariant.
  10. One repository if the root needs global write access — it accepts only this root and loads/saves the whole cluster. Use a factory only when construction would leak interior types or skip invariants.

Done when: every mutation path goes through the root; foreign aggregates are ids; each value object is immutable and equal by components; events are past-tense, registered after success, published after persist; the repository — if any — accepts only this root; no repository method holds a business rule.

Tripwires

  • A package or topic tagged ddd offered as the model — inspect for invariants on roots and immutable value objects, or write "DDD-in-name-only" and model from experts. When copying a sample repo, read the matching section of references/pitfalls.md.
  • A multi-step prompt about to emit aggregates or hexagons from chat history — stop at glossary / event list / BC proposals; validate uncertain in-scope context proposals against domain evidence before generating their aggregates; reuse accepted boundaries. When the loop is an LLM generation, read the matching section of references/pitfalls.md.
  • A reach for an event store or a new microservice "to do DDD" — keep one write model and one database; split a query model only when a named read is blocked by aggregate constraints. When CQRS or Event Sourcing is proposed as the default, read the matching section of references/pitfalls.md.
  • A *Service about to own a new invariant — put the rule on the entity or value object; name the application service with a verb.
  • Hexagonal ports chosen as proof of DDD — hexagonal + transaction script is a valid Downgrade; tactical DDD still requires a Domain Model inside the context.
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

skills/mine/ddd-master

Default branch

main

Latest commit

0422940

Tree SHA

d2996c2