clean-ddd-hexagonal

Language-agnostic backend architecture combining DDD, Clean Architecture, and Hexagonal patterns. Enforces strict dependency rules (inward only) with clear layer separation: domain (core logic), application (use cases), and infrastructure (adapters) Provides tactical DDD patterns including entities, value objects, aggregates, domain events, repositories, and domain services with concrete decision trees for placement Includes anti-pattern warnings (anemic models, god aggregates, leaking infrastructure, premature CQRS) and implementation sequencing from domain discovery through adapter implementation Covers aggregate boundary design, repository-per-aggregate strategy, eventual consistency via domain events, and transaction management across service boundaries Language-agnostic guidance applicable to Go, Rust, Python, TypeScript, Java, and C# with reference documentation on layers, bounded contexts, CQRS, event sourcing, and testing strategies

INSTALLATION
npx skills add https://github.com/ccheney/robust-skills --skill clean-ddd-hexagonal
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2d

Pattern Boundaries

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

CRITICAL: The Dependency Rule

Dependencies point inward only. Outer layers depend on inner layers, never the reverse.

Infrastructure → Application → Domain

   (adapters)     (use cases)    (core)

Violations to catch:

  • Domain importing database/HTTP libraries
  • In this architecture style, controllers calling repositories directly instead of application use cases
  • Entities depending on application services

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.

Quick Decision Trees

"Where does this code go?"

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)

"Is this an Entity or Value Object?"

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)

"Should this be its own Aggregate?"

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).

Directory Structure

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.

DDD Building Blocks

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-Patterns (CRITICAL)

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

Implementation Order

  • Discover the Domain — Event Storming, conversations with domain experts
  • Model the Domain — Entities, value objects, aggregates (no infra)
  • Define Ports — Repository interfaces, external service interfaces
  • Implement Use Cases — Application services coordinating domain
  • Add Adapters last — HTTP, database, messaging implementations

DDD is collaborative. Modeling sessions with domain experts are as important as the code patterns.

Reference Documentation

File

Purpose

references/LAYERS.md

Complete layer specifications

references/DDD-STRATEGIC.md

Bounded contexts, context mapping

references/DDD-TACTICAL.md

Entities, value objects, aggregates (pseudocode)

references/HEXAGONAL.md

Ports, adapters, naming

references/CQRS-EVENTS.md

Command/query separation, events

references/TESTING.md

Unit, integration, architecture tests

references/CHEATSHEET.md

Quick decision guide

Sources

Primary Sources

Primary Pattern References

  • CQRS — Martin Fowler

Implementation Guides

Supplemental Syntheses

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card