arch-ddd
Apply Domain-Driven Design (DDD) architecture to backend projects. Use for tasks like defining bounded contexts, aggregates and invariants, entities/value objects, domain services, repositories, domain events, application services, anti-corruption layers, and aligning code structure and APIs with domain language while avoiding anemic models.
When & Why to Use This Skill
This Claude skill facilitates the implementation of Domain-Driven Design (DDD) for backend systems, helping developers create maintainable, scalable, and business-aligned architectures. It provides expert guidance on defining bounded contexts, aggregates, and domain-centric layers, ensuring that complex business logic remains decoupled from infrastructure concerns while preventing common pitfalls like anemic domain models.
Use Cases
- Case 1: Designing a new microservices-based backend from scratch by identifying bounded contexts and defining clear integration contracts.
- Case 2: Refactoring a legacy 'anemic' monolith where business logic is scattered across service layers into a structured, rich domain model.
- Case 3: Establishing a 'Ubiquitous Language' to align technical implementation, API design, and documentation with core business terminology.
- Case 4: Implementing complex business invariants and transactional consistency boundaries using Aggregate Roots and Domain Events.
- Case 5: Building an Anti-Corruption Layer (ACL) to protect a new system's domain model when integrating with legacy external APIs or third-party services.
- Case 6: Organizing project codebases using Ports and Adapters (Hexagonal Architecture) to ensure the domain layer remains independent of databases and frameworks.
| name | arch-ddd |
|---|---|
| description | Apply Domain-Driven Design (DDD) architecture to backend projects. Use for tasks like defining bounded contexts, aggregates and invariants, entities/value objects, domain services, repositories, domain events, application services, anti-corruption layers, and aligning code structure and APIs with domain language while avoiding anemic models. |
arch-ddd
Use this skill to design or refactor a backend system toward DDD (领域驱动设计) with clear boundaries and maintainable evolution.
Core principles (practical)
- Ubiquitous Language: domain terms in code, APIs, and docs must match.
- Bounded Contexts: separate subdomains with explicit boundaries; integrate via contracts.
- Aggregate: the unit of consistency; enforce invariants inside the aggregate.
- Application vs Domain: application services orchestrate; domain model owns rules.
- Ports & Adapters: infrastructure depends on domain/application, not the other way around.
Deliverables (what “good” looks like)
- A list of bounded contexts + their responsibilities and integration points.
- Aggregate definitions (root, entities, value objects) + invariants.
- Command/query use-cases mapped to application services.
- Repository interfaces (in domain/application) + infra implementations.
- Domain events for cross-context integration (outbox if needed).
Workflow
- Understand the domain
- Identify actors, key workflows, nouns/verbs, and business constraints.
- Extract invariants (must always be true) and policies (may change).
- Split bounded contexts
- Group capabilities that change together.
- Define context boundaries and “ownership” of data/behaviors.
- For each boundary: define integration style (sync API, async events, file/batch).
- Define aggregates
- Start from invariants and transactions, not tables.
- Choose one aggregate root per consistency boundary.
- Keep aggregates small; reference other aggregates by ID only.
- Define application services (use cases)
- Each endpoint maps to a use-case (command/query).
- Commands: validate, load aggregate, execute domain behavior, persist, publish events.
- Queries: read-optimized models (can be denormalized) and avoid domain coupling.
- Persistence strategy
- Repository interface returns aggregates; hide ORM/SQL details.
- Avoid cross-aggregate joins in write paths; consider read models for queries.
- Use domain IDs (string/ULID/UUID) consistently across layers.
- Integration patterns
- Cross-context sync: explicit contract DTOs; add Anti-Corruption Layer (ACL) when mapping is non-trivial.
- Cross-context async: domain events; versioned payloads; idempotent consumers.
- Testing approach
- Domain: fast unit tests around invariants and behaviors.
- Application: use-case tests with fakes for repositories/outbox.
- Integration: contract tests for APIs/events; DB tests only where needed.
Anti-patterns to avoid
- “Everything is a service”: domain logic scattered in application/service layer.
- Anemic domain model: entities are just getters/setters.
- Aggregate too large: one aggregate per table or “user” becomes god object.
- Tight coupling to DB schema: domain types leak ORM annotations everywhere.
Code organization (suggested)
domain/: aggregates, entities, value objects, domain services, domain events, repository interfacesapplication/: use-cases, command/query handlers, DTOs, mappers, transaction boundaryinfrastructure/: DB/ORM, message bus, external clients, repository implementationsinterfaces/(orapi/): controllers/routers, request/response models, auth