Files
architecture/skills/ddd/SKILL.md
Hugo Nijhuis 6e4ff3af86 feat: add DDD capability for vision-to-issues workflow
Add complete DDD capability set for breaking down product vision into
implementation issues using Domain-Driven Design principles.

Components:
- issue-writing skill: Enhanced with user story format and vertical slices
- ddd skill: Strategic and tactical DDD patterns (bounded contexts, aggregates, commands, events)
- ddd-breakdown skill: User-invocable workflow (/ddd-breakdown)
- ddd-analyst agent: Analyzes manifesto/vision/code, generates DDD-structured user stories

Workflow: Read manifesto + vision → analyze codebase → identify bounded contexts
→ map features to DDD patterns → generate user stories → create Gitea issues

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-01-12 13:02:56 +01:00

7.5 KiB

name, description, user-invocable
name description user-invocable
ddd Domain-Driven Design concepts: bounded contexts, aggregates, commands, events, and tactical patterns. Use when analyzing domain models, identifying bounded contexts, or mapping features to DDD patterns. false

Domain-Driven Design (DDD)

Strategic and tactical patterns for modeling complex domains.

Strategic DDD: Bounded Contexts

What is a Bounded Context?

A bounded context is a boundary within which a domain model is consistent. Same terms can mean different things in different contexts.

Example: "Order" means different things in different contexts:

  • Sales Context: Order = customer purchase with payment and shipping
  • Fulfillment Context: Order = pick list for warehouse
  • Accounting Context: Order = revenue transaction

Identifying Bounded Contexts

Look for:

  1. Different language: Same term means different things
  2. Different models: Same concept has different attributes/behavior
  3. Different teams: Natural organizational boundaries
  4. Different lifecycles: Entities created/destroyed at different times
  5. Different rate of change: Some areas evolve faster than others

From vision/manifesto:

  • Identify personas → each persona likely interacts with different contexts
  • Identify core domain concepts → group related concepts into contexts
  • Identify capabilities → capabilities often align with contexts

From existing code:

  • Look for packages/modules that cluster related concepts
  • Identify seams where code is loosely coupled
  • Look for translation layers between subsystems
  • Identify areas where same terms mean different things

Context Boundaries

Good boundaries:

  • Clear interfaces between contexts
  • Each context owns its data
  • Contexts communicate via events or APIs
  • Minimal coupling between contexts

Bad boundaries:

  • Shared database tables across contexts
  • Direct object references across contexts
  • Mixed concerns within a context

Common Context Patterns

Pattern Description Example
Core Domain Your unique competitive advantage Custom business logic
Supporting Subdomain Necessary but not differentiating User management
Generic Subdomain Common problems, use off-the-shelf Email sending, file storage

Tactical DDD: Building Blocks

Aggregates

An aggregate is a cluster of entities and value objects treated as a unit for data changes.

Rules:

  • One entity is the aggregate root (only entity referenced from outside)
  • All changes go through the root
  • Enforce business invariants within the aggregate
  • Keep aggregates small (2-3 entities max when possible)

Example:

Order (root)
├── OrderLine
├── ShippingAddress
└── Payment

External code only references Order, never OrderLine directly.

Identifying aggregates:

  • What entities always change together?
  • What invariants must be enforced?
  • What is the transactional boundary?

Commands

Commands represent intent to change state. Named with imperative verbs.

Format: [Verb][AggregateRoot] or [AggregateRoot][Verb]

Examples:

  • PlaceOrder or OrderPlace
  • CancelSubscription or SubscriptionCancel
  • ApproveInvoice or InvoiceApprove

Commands:

  • Are handled by the aggregate root
  • Either succeed completely or fail
  • Can be rejected (return error)
  • Represent user intent or system action

Events

Events represent facts that happened in the past. Named in past tense.

Format: [AggregateRoot][PastVerb] or [Something]Happened

Examples:

  • OrderPlaced
  • SubscriptionCancelled
  • InvoiceApproved
  • PaymentFailed

Events:

  • Are immutable (already happened)
  • Can be published to other contexts
  • Enable eventual consistency
  • Create audit trail

Value Objects

Value Objects are immutable objects defined by their attributes, not identity.

Examples:

  • Money (amount + currency)
  • EmailAddress
  • DateRange
  • Address

Characteristics:

  • No identity (two with same values are equal)
  • Immutable (cannot change, create new instance)
  • Can contain validation logic
  • Can contain behavior

When to use:

  • Concept has no lifecycle (no create/update/delete)
  • Equality is based on attributes, not identity
  • Can be shared/reused

Entities

Entities have identity that persists over time, even if attributes change.

Examples:

  • User (ID remains same even if name/email changes)
  • Order (ID remains same through lifecycle)
  • Product (ID remains same even if price changes)

Characteristics:

  • Has unique identifier
  • Can change over time
  • Identity matters more than attributes

Mapping Features to DDD Patterns

Process

For each feature from vision:

  1. Identify the bounded context: Which context does this belong to?

  2. Identify the aggregate(s): What entities/value objects are involved?

  3. Identify commands: What actions can users/systems take?

  4. Identify events: What facts should be recorded when commands succeed?

  5. Identify value objects: What concepts are attribute-defined, not identity-defined?

Example: "User can place an order"

Bounded Context: Sales

Aggregate: Order (root)

  • OrderLine (entity)
  • ShippingAddress (value object)
  • Money (value object)

Commands:

  • PlaceOrder
  • AddOrderLine
  • RemoveOrderLine
  • UpdateShippingAddress

Events:

  • OrderPlaced
  • OrderLineAdded
  • OrderLineRemoved
  • ShippingAddressUpdated

Value Objects:

  • Money (amount, currency)
  • Address (street, city, zip, country)
  • Quantity

Refactoring to DDD

When existing code doesn't follow DDD patterns:

Identify Misalignments

Anemic domain model:

  • Entities with only getters/setters
  • Business logic in services, not entities
  • Fix: Move behavior into aggregates

God objects:

  • One entity doing too much
  • Fix: Split into multiple aggregates or value objects

Context leakage:

  • Same model shared across contexts
  • Fix: Create context-specific models with translation layers

Missing boundaries:

  • Everything in one module/package
  • Fix: Identify bounded contexts, separate into modules

Refactoring Strategies

Extract bounded context:

As a developer, I want to extract [Context] into a separate module,
so that it has clear boundaries and can evolve independently

Extract aggregate:

As a developer, I want to extract [Aggregate] from [GodObject],
so that it enforces its own invariants

Introduce value object:

As a developer, I want to replace [primitive] with [ValueObject],
so that validation is centralized and the domain model is clearer

Introduce event:

As a developer, I want to publish [Event] when [Command] succeeds,
so that other contexts can react to state changes

Anti-Patterns

Avoid:

  • Aggregates spanning multiple bounded contexts
  • Shared mutable state across contexts
  • Direct database access across contexts
  • Aggregates with dozens of entities (too large)
  • Value objects with identity
  • Commands without clear aggregate ownership
  • Events that imply future actions (use commands)

Tips

  • Start with strategic DDD (bounded contexts) before tactical patterns
  • Bounded contexts align with team/organizational boundaries
  • Keep aggregates small (single entity when possible)
  • Use events for cross-context communication
  • Value objects make impossible states impossible
  • Refactor incrementally - don't rewrite everything at once