# Ddd

> Domain Driven Design in JAVA

- Skill: `bensimpson-ch/ddd` (Agent Skill)
- Install (CLI): `npx skillmds@latest add bensimpson-ch/ddd`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bensimpson-ch/ddd/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: bensimpson-ch (https://skillmd.com/u/bensimpson-ch)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/bensimpson-ch/ddd

---


# Domain Driven Design in JAVA

## Usage

Parse the following from `$ARGUMENTS`:
- **domain description** (required): what the domain is about
- **aggregate names** (required): at least one aggregate name

If either is missing, print the following and STOP:

```
Usage: /ddd <domain description>: <Aggregate1>, <Aggregate2>, ...

Example: /ddd selling t-shirts online: Order, Product, Customer
```

## Existing Domain Detection

Before starting, check if the domain module contains a `CLAUDE.md`. If it does, read it.  This 
contains domain decisions from a previous session. Use it as the starting point instead of 
asking the user to re-describe the domain from scratch. When ddd-coach rules conflict with 
decisions recorded in a previous CLAUDE.md, the coach rules win. The coach evolves faster 
than any single project's documentation.

If the domain module has existing code but the user invoked `/ddd` with new arguments, ask:
- **Add aggregates**: extend the existing domain with the new aggregates
- **Review**: audit existing code against ddd-coach rules and suggest improvements

## Process

Follow the rules defined in the `ddd-coach` skill for all generated code.

### 1. Sketch the Domain Model

For each aggregate named in the input, propose:
- The aggregate root and its typed ID
- Likely value objects based on the domain description
- Relationships between aggregates (by ID reference, never direct)
- Repository interface
- Ports, if the domain description implies outbound operations

The sketch must follow ddd-coach rules. No raw primitives. Every field in the diagram is a 
typed value object. If the code would have `Money`, the diagram has `Money`, not `int amountCents` 
and `String currency`. The sketch is the domain model, not an ER diagram. Show invariants on 
value objects in the sketch: `Quantity(int > 0)`, `Money(BigDecimal >= 0)`. The user reviews 
constraints before code is generated, not after. Mark non-empty collections: 
`OrderItems(Set<OrderItem>) non-empty`. If the domain requires at least one item, show it.

Use what Java already provides before inventing types. `java.util.Currency` exists. Don't wrap 
a `String`. For well-known domain concepts like money, time, or locale, research established 
patterns and use them intelligently.

Present the sketch as an ASCII class diagram in the conversation. Write the PlantUML version 
silently to disk (see step 3 for location). Do not stream the `.puml` content in the 
conversation.

### 2. Ask the User

After presenting the ASCII sketch, inform the user that PlantUML diagrams have been written to 
`src/site/domain-classdiagram.puml` and `src/site/domain-aggregates.puml`, then ask:
- **Does this look right?** Let the user correct, add, or remove before any code is generated. 
  This is an invitation to iterate and clarify.
- **Iterate or all at once?** The default is to build one aggregate at a time with feedback 
  between each (see Aggregate Build Strategy below). Offer all-at-once as an option for 
  developers who prefer speed over token efficiency.

### 3. Generate

#### Aggregate Build Strategy

Build one aggregate at a time, starting from the aggregate with the fewest dependencies. After each 
aggregate, confirm the public interface before proceeding. Downstream aggregates reference 
upstream value objects, identity types, and domain events.

Before generating, estimate total output. If the deliverable exceeds 800 lines, present a 
numbered build plan and proceed aggregate by aggregate. Otherwise, generate in a single pass.

Never generate all aggregates in one pass when there are cross-aggregate references. The cheapest 
token is the one you never send. Catching a boundary mistake after one aggregate costs one 
regeneration. Catching it after all aggregates costs a full rework.

Based on the user's choice, generate the domain code:

For each aggregate:
- Aggregate root with typed ID, value objects, and guards
- First-class collections where collections exist
- Repository interface
- Ports if applicable
- Domain events if the domain description implies them
- Unit tests for all types with logic

At the domain root:
- `Guard.java`
- `ConstraintViolationException.java`

All PlantUML diagrams go in the **project root's** `src/site/` directory. The do NOT go inside the domain 
module. The domain is one module in a multi-module project. This follows the Maven site 
convention.  For Gradle or other build tools, ask the user where to place it.

Generate two PlantUML diagrams. Both are living documents. Update them as the domain evolves:

- `src/site/domain-classdiagram.puml`: class diagram showing aggregates, value objects, and 
  their fields.
- `src/site/domain-aggregates.puml`: component diagram showing aggregates and how they relate 
  to each other. Dependencies flow one direction. No circular references. This diagram makes 
  the aggregate hierarchy visible.

Write a `CLAUDE.md` in the domain module root describing the domain model: what aggregates exist, 
what they contain, key decisions made during the conversation, and any domain rules the user 
specified. This file is picked up automatically by Claude in future sessions, so the user never 
has to re-explain the domain.

### 4. Review

After generating, present a summary of what was created and ask if the user wants to 
adjust anything before moving on.

---

Author: Benjamin Simpson ([bensimpson-ch](https://github.com/bensimpson-ch))

