Applies Clean Architecture, DDD, and Hexagonal patterns for designing maintainable backend services. Triggers on domain modeling, aggregates, ports/adapters, CQRS, and event sourcing.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ccheney-robust-skills:clean-ddd-hexagonalThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Backend architecture combining DDD tactical patterns, Clean Architecture dependency rules, and Hexagonal ports/adapters for maintainable, testable systems.
Backend architecture combining DDD tactical patterns, Clean Architecture dependency rules, and Hexagonal ports/adapters for maintainable, testable systems.
This skill is an opinionated synthesis of several related architecture traditions. It is not a single canonical architecture model. Use the original source that matches the design question you are answering: DDD for domain modeling, Hexagonal Architecture for ports/adapters, Clean Architecture for dependency direction, Onion Architecture for domain-centered layering, and CQRS/Event Sourcing only for specific read/write or temporal requirements.
| Use When | Skip When |
|---|---|
| Complex business domain with many rules | Simple CRUD, few business rules |
| Long-lived system (years of maintenance) | Prototype, MVP, throwaway code |
| Team of 5+ developers | Solo developer or small team (1-2) |
| Multiple entry points (API, CLI, events) | Single entry point, simple API |
| Need to swap infrastructure (DB, broker) | Fixed infrastructure, unlikely to change |
| High test coverage required | Quick scripts, internal tools |
Start simple. Evolve complexity only when needed. Most systems don't need full CQRS or Event Sourcing.
| Pattern | Primary Question | Use It For | Do Not Treat As |
|---|---|---|---|
| DDD | How do we model a complex business domain? | Ubiquitous language, bounded contexts, aggregates, value objects | A folder structure by itself |
| Hexagonal Architecture | How does the application interact with the outside world? | Ports, driver adapters, driven adapters, testable application core | A mandate for six sides or one exact package layout |
| Clean Architecture | Which direction should dependencies point? | Inward dependency rule, use case boundaries, framework independence | A universal four-folder template |
| Onion Architecture | How do we keep the domain model central? | Domain-centered layers and dependency inversion | A separate requirement when Clean/Hexagonal already solve the local problem |
| CQRS | Do reads and writes need different models? | Bounded contexts with divergent read/write workloads | A default application architecture |
| Event Sourcing | Do we need state from a complete event history? | Audit, temporal queries, replayable workflows | A persistence default for CRUD systems |
Dependencies point inward only. Outer layers depend on inner layers, never the reverse.
Infrastructure → Application → Domain
(adapters) (use cases) (core)
Violations to catch:
Design validation: "Create your application to work without either a UI or a database" — Alistair Cockburn. If you can run your domain logic from tests with no infrastructure, your boundaries are correct.
Where does it go?
├─ Pure business logic, no I/O → domain/
├─ Orchestrates domain + has side effects → application/
├─ Talks to external systems → infrastructure/
├─ Defines HOW to interact (interface) → port (domain or application)
└─ Implements a port → adapter (infrastructure)
Sharp edges — the placements LLMs most often get wrong:
| Code | Layer | Why |
|---|---|---|
| Business invariant ("order needs items to confirm") | Domain (entity method) | It's a rule, not orchestration |
| Input format validation (JSON shape, required fields) | Adapter (controller/DTO) | Protocol concern, not business rule |
| Transaction begin/commit | Application | Use case = transaction boundary |
| ORM entity / table model | Infrastructure | Map to domain objects; never let ORM entities BE domain entities |
| Domain ↔ DB mapping | Infrastructure (mapper) | Persistence detail |
| Authorization ("is user allowed?") | Application (policy) or adapter middleware | Domain stays auth-agnostic; encode role RULES in domain only if they're business rules |
| Clock, UUID generation | Port in domain/application; adapter in infrastructure | Keeps domain deterministic and testable |
| Reacting to a domain event | Application (event handler) | Side effects = orchestration |
| Query joining many tables for a screen | Read model (application interface, infrastructure impl) | Don't force it through aggregates |
Litmus test for anemic domain models: if an application service reads state out of an entity, decides, then writes state back (if (order.status === 'draft') order.status = 'confirmed'), move that logic into the entity as order.confirm(). Handlers should read like a script: load aggregate → call one behavior method → save → publish.
Entity or Value Object?
├─ Has unique identity that persists → Entity
├─ Defined only by its attributes → Value Object
├─ "Is this THE same thing?" → Entity (identity comparison)
└─ "Does this have the same value?" → Value Object (structural equality)
Aggregate boundaries?
├─ Must be consistent together in a transaction → Same aggregate
├─ Can be eventually consistent → Separate aggregates
├─ Referenced by ID only → Separate aggregates
└─ >10 entities in aggregate → Split it
Rule: One aggregate per transaction. Cross-aggregate consistency via domain events (eventual consistency).
src/
├── domain/ # Core business logic (NO external dependencies)
│ ├── {aggregate}/
│ │ ├── entity # Aggregate root + child entities
│ │ ├── value_objects # Immutable value types
│ │ ├── events # Domain events
│ │ ├── repository # DDD repository interface (driven port)
│ │ └── services # Domain services (stateless logic)
│ └── shared/
│ └── errors # Domain errors
├── application/ # Use cases / Application services
│ ├── {use-case}/
│ │ ├── command # Command/Query DTOs
│ │ ├── handler # Use case implementation
│ │ └── port # Driver port interface
│ └── shared/
│ └── unit_of_work # Transaction abstraction
├── infrastructure/ # Adapters (external concerns)
│ ├── persistence/ # Database adapters
│ ├── messaging/ # Message broker adapters
│ ├── http/ # REST/GraphQL adapters (DRIVER)
│ └── config/
│ └── di # Dependency injection / composition root
└── main # Bootstrap / entry point
Port placement: This skill defaults to a DDD-centered layout where aggregate repository interfaces live beside the aggregate in domain/. A stricter Hexagonal layout may instead put driven ports under application/ports/driven/. Pick one convention per codebase and keep the dependency rule intact.
Presentation layer: Driver adapters (REST/gRPC/CLI) live under infrastructure/ in this default layout. Some codebases lift them into a fourth top-level presentation/ layer instead (references/LAYERS.md shows that variant). Use one home for controllers, not both.
Event publishing: Saving an aggregate and then publishing its events to a broker are two writes; a crash between them silently drops events. When events must reach other services reliably, write them to an outbox table in the same transaction as the aggregate — see the outbox pattern in references/CQRS-EVENTS.md.
| Pattern | Purpose | Layer | Key Rule |
|---|---|---|---|
| Entity | Identity + behavior | Domain | Equality by ID |
| Value Object | Immutable data | Domain | Equality by value, no setters |
| Aggregate | Consistency boundary | Domain | Only root is referenced externally |
| Domain Event | Record of change | Domain | Past tense naming (OrderPlaced) |
| Repository | Persistence abstraction | Domain (port) | Per aggregate, not per table |
| Domain Service | Stateless logic | Domain | When logic doesn't fit an entity |
| Application Service | Orchestration | Application | Coordinates domain + infra |
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Anemic Domain Model | Entities are data bags, logic in services | Move behavior INTO entities |
| Repository per Entity | Breaks aggregate boundaries | One repository per AGGREGATE |
| Leaking Infrastructure | Domain imports DB/HTTP libs | Domain has ZERO external deps |
| God Aggregate | Too many entities, slow transactions | Split into smaller aggregates |
| Skipping Use Cases | Controllers call repositories directly in a use-case architecture | Route through application use cases |
| CRUD Thinking | Modeling data, not behavior | Model business operations |
| Premature CQRS | Adding complexity before needed | Start with simple read/write, evolve |
| Cross-Aggregate TX | Multiple aggregates in one transaction | Use domain events for consistency |
DDD is collaborative. Modeling sessions with domain experts are as important as the code patterns.
Read the matching file before doing the task in the left column:
| Before you... | Read |
|---|---|
| Write code in any layer, wire dependency injection, or decide 3-layer vs 4-layer | references/LAYERS.md |
| Split a system into services/contexts, integrate with a legacy or third-party system (ACL), run Event Storming | references/DDD-STRATEGIC.md |
| Model an entity, value object, aggregate, repository, domain service, or factory | references/DDD-TACTICAL.md |
| Define ports/adapters, name interfaces, or lay out a ports-first structure | references/HEXAGONAL.md |
| Add commands/queries, domain vs integration events, outbox, sagas, or evaluate CQRS/Event Sourcing | references/CQRS-EVENTS.md |
| Write unit/integration/architecture tests for any layer | references/TESTING.md |
| Answer a quick "which pattern/which layer" question without deep-diving | references/CHEATSHEET.md |
npx claudepluginhub ccheney/robust-skillsGuides applying Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to structure systems with isolated business logic, layer boundaries, and dependency rules.
Implements Clean Architecture, Hexagonal Architecture, and Domain-Driven Design for backend services. Helps design microservices, refactor monoliths with bounded contexts, and resolve dependency cycles.
Implements Clean Architecture, Hexagonal Architecture, and Domain-Driven Design for backend systems. Use when architecting new systems or refactoring for maintainability.