clean-ddd-hexagonal
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClean Architecture + DDD + Hexagonal
Clean Architecture + DDD + Hexagonal
Backend architecture combining DDD tactical patterns, Clean Architecture dependency rules, and Hexagonal ports/adapters for maintainable, testable systems.
结合DDD战术模式、Clean Architecture依赖规则和Hexagonal端口/适配器模式的后端架构,构建可维护、可测试的系统。
When to Use (and When NOT to)
适用与不适用场景
| 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.
| 适用场景 | 不适用场景 |
|---|---|
| 具有大量规则的复杂业务领域 | 简单CRUD操作,业务规则少 |
| 需长期维护的系统(持续数年) | 原型、MVP、一次性代码 |
| 5人及以上的开发团队 | 独立开发者或小型团队(1-2人) |
| 多入口点(API、CLI、事件) | 单一入口点,简单API |
| 需要更换基础设施(数据库、消息中间件) | 基础设施固定,几乎不会变更 |
| 要求高测试覆盖率 | 快速脚本、内部工具 |
从简单开始。仅在需要时再增加复杂度。 大多数系统不需要完整的CQRS或事件溯源。
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
- Controllers calling repositories directly (bypassing 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.
依赖关系仅向内指向。外层依赖内层,反之则不可。
Infrastructure → Application → Domain
(adapters) (use cases) (core)需要避免的违规情况:
- 领域层引入数据库/HTTP库
- 控制器直接调用仓库(绕过用例)
- 实体依赖应用服务
设计验证标准: “让你的应用在没有UI或数据库的情况下也能运行”——Alistair Cockburn。如果你的领域逻辑可以在不依赖任何基础设施的情况下通过测试运行,说明你的边界设计是正确的。
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)代码归属?
├─ 纯业务逻辑,无I/O操作 → domain/
├─ 编排领域逻辑 + 包含副作用 → application/
├─ 与外部系统交互 → infrastructure/
├─ 定义交互方式(接口) → 端口(领域层或应用层)
└─ 实现端口 → 适配器(基础设施层)"Is this an Entity or Value Object?"
“这是Entity还是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)实体还是值对象?
├─ 具有持久化的唯一标识 → Entity
├─ 仅由属性定义 → Value Object
├─ “这是同一个事物吗?” → Entity(按标识比较)
└─ “它们的值是否相同?” → Value Object(按结构相等性比较)"Should this be its own Aggregate?"
“这应该作为独立的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 itRule: One aggregate per transaction. Cross-aggregate consistency via domain events (eventual consistency).
聚合边界?
├─ 必须在事务中保持一致 → 同一聚合
├─ 可最终一致 → 独立聚合
├─ 仅通过ID引用 → 独立聚合
└─ 聚合内包含10个以上实体 → 拆分聚合规则: 一个事务对应一个聚合。跨聚合的一致性通过领域事件实现(最终一致)。
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 # 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 pointsrc/
├── domain/ # 核心业务逻辑(无外部依赖)
│ ├── {aggregate}/
│ │ ├── entity # 聚合根 + 子实体
│ │ ├── value_objects # 不可变值类型
│ │ ├── events # 领域事件
│ │ ├── repository # 仓库接口(驱动端口)
│ │ └── services # 领域服务(无状态逻辑)
│ └── shared/
│ └── errors # 领域错误
├── application/ # 用例 / 应用服务
│ ├── {use-case}/
│ │ ├── command # 命令/查询DTO
│ │ ├── handler # 用例实现
│ │ └── port # 驱动端口接口
│ └── shared/
│ └── unit_of_work # 事务抽象
├── infrastructure/ # 适配器(外部相关实现)
│ ├── persistence/ # 数据库适配器
│ ├── messaging/ # 消息中间件适配器
│ ├── http/ # REST/GraphQL适配器(驱动端)
│ └── config/
│ └── di # 依赖注入 / 组合根
└── main # 启动程序 / 入口点DDD Building Blocks
DDD构建块
| 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 ( |
| 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 |
| 模式 | 用途 | 层级 | 核心规则 |
|---|---|---|---|
| Entity | 标识 + 行为 | 领域层 | 按ID判断相等性 |
| Value Object | 不可变数据 | 领域层 | 按值判断相等性,无setter |
| Aggregate | 一致性边界 | 领域层 | 仅聚合根可被外部引用 |
| Domain Event | 记录变更 | 领域层 | 过去式命名(如 |
| Repository | 持久化抽象 | 领域层(端口) | 每个聚合对应一个仓库,而非每个表 |
| Domain Service | 无状态逻辑 | 领域层 | 当逻辑不适合放在实体中时使用 |
| Application Service | 编排协调 | 应用层 | 协调领域层与基础设施层 |
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 Ports | Controllers → Repositories directly | Always go through application layer |
| 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 |
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 贫血领域模型 | 实体仅作为数据容器,逻辑放在服务中 | 将逻辑迁移到实体内部 |
| 每个实体对应一个仓库 | 破坏聚合边界 | 每个聚合对应一个仓库 |
| 基础设施层泄漏 | 领域层引入DB/HTTP库 | 领域层无任何外部依赖 |
| 上帝聚合 | 包含过多实体,事务缓慢 | 拆分为更小的聚合 |
| 跳过端口 | 控制器直接调用仓库 | 始终通过应用层进行调用 |
| CRUD思维 | 仅建模数据,而非行为 | 建模业务操作 |
| 过早引入CQRS | 在不需要时增加复杂度 | 从简单的读写逻辑开始,按需演进 |
| 跨聚合事务 | 一个事务包含多个聚合 | 使用领域事件实现一致性 |
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.
- 领域探索 — 事件风暴、与领域专家沟通
- 领域建模 — 实体、值对象、聚合(无基础设施)
- 定义端口 — 仓库接口、外部服务接口
- 实现用例 — 协调领域层的应用服务
- 最后添加适配器 — HTTP、数据库、消息中间件实现
DDD是协作式的。 与领域专家的建模会议和代码模式同样重要。
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 |
| 文件 | 用途 |
|---|---|
| references/LAYERS.md | 完整的层级规范 |
| references/DDD-STRATEGIC.md | 限界上下文、上下文映射 |
| references/DDD-TACTICAL.md | 实体、值对象、聚合(伪代码) |
| references/HEXAGONAL.md | 端口、适配器、命名规范 |
| references/CQRS-EVENTS.md | 命令/查询分离、事件 |
| references/TESTING.md | 单元测试、集成测试、架构测试 |
| references/CHEATSHEET.md | 快速决策指南 |
Sources
资料来源
Primary Sources
主要资料
- The Clean Architecture — Robert C. Martin (2012)
- Hexagonal Architecture — Alistair Cockburn (2005)
- Domain-Driven Design: The Blue Book — Eric Evans (2003)
- Implementing Domain-Driven Design — Vaughn Vernon (2013)
- The Clean Architecture — Robert C. Martin (2012)
- Hexagonal Architecture — Alistair Cockburn (2005)
- Domain-Driven Design: The Blue Book — Eric Evans (2003)
- Implementing Domain-Driven Design — Vaughn Vernon (2013)
Pattern References
模式参考
- CQRS — Martin Fowler
- Event Sourcing — Martin Fowler
- Repository Pattern — Martin Fowler (PoEAA)
- Unit of Work — Martin Fowler (PoEAA)
- Bounded Context — Martin Fowler
- Transactional Outbox — microservices.io
- Effective Aggregate Design — Vaughn Vernon
- CQRS — Martin Fowler
- Event Sourcing — Martin Fowler
- Repository Pattern — Martin Fowler (PoEAA)
- Unit of Work — Martin Fowler (PoEAA)
- Bounded Context — Martin Fowler
- Transactional Outbox — microservices.io
- Effective Aggregate Design — Vaughn Vernon
Implementation Guides
实施指南
- Microsoft: DDD + CQRS Microservices
- Domain Events — Udi Dahan
- Microsoft: DDD + CQRS Microservices
- Domain Events — Udi Dahan