clean-ddd-hexagonal by ccheney/robust-skills
npx skills add https://github.com/ccheney/robust-skills --skill clean-ddd-hexagonal结合 DDD 战术模式、整洁架构依赖规则和六边形架构端口/适配器的后端架构,用于构建可维护、可测试的系统。
| 适用场景 | 应避免的场景 |
|---|---|
| 具有复杂业务规则的业务领域 | 简单的 CRUD,业务规则很少 |
| 长期维护的系统(数年) | 原型、MVP、一次性代码 |
| 5 名以上开发人员的团队 | 独立开发者或小团队(1-2人) |
| 多个入口点(API、CLI、事件) | 单一入口点,简单的 API |
| 需要更换基础设施(数据库、消息代理) | 基础设施固定,不太可能变更 |
| 需要高测试覆盖率 | 快速脚本,内部工具 |
从简单开始。仅在需要时演进复杂性。 大多数系统不需要完整的 CQRS 或事件溯源。
依赖关系仅指向内部。外层依赖内层,反之则不行。
Infrastructure → Application → Domain
(适配器) (用例) (核心)
需要警惕的违规情况:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
设计验证: "创建你的应用程序,使其无需 UI 或数据库即可工作" — Alistair Cockburn。如果你可以在没有基础设施的情况下,通过测试运行你的领域逻辑,那么你的边界划分就是正确的。
Where does it go?
├─ 纯业务逻辑,无 I/O → domain/
├─ 编排领域逻辑并产生副作用 → application/
├─ 与外部系统通信 → infrastructure/
├─ 定义交互方式(接口) → port (domain 或 application)
└─ 实现一个端口 → adapter (infrastructure)
Entity or Value Object?
├─ 具有持久化的唯一标识符 → Entity
├─ 仅由其属性定义 → Value Object
├─ "这是'同一个'东西吗?" → Entity (标识符比较)
└─ "这具有相同的值吗?" → Value Object (结构相等性比较)
Aggregate boundaries?
├─ 必须在同一个事务中保持一致 → 同一个聚合
├─ 可以最终一致 → 独立的聚合
├─ 仅通过 ID 引用 → 独立的聚合
└─ 聚合内实体数量 > 10 → 拆分它
规则: 每个事务一个聚合。跨聚合的一致性通过领域事件实现(最终一致性)。
src/
├── 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 # 引导程序 / 入口点
| 模式 | 目的 | 所在层 | 关键规则 |
|---|---|---|---|
| 实体 | 标识 + 行为 | Domain | 通过 ID 判断相等性 |
| 值对象 | 不可变数据 | Domain | 通过值判断相等性,无 setter |
| 聚合 | 一致性边界 | Domain | 外部仅引用聚合根 |
| 领域事件 | 变更记录 | Domain | 过去时命名(如 OrderPlaced) |
| 仓储 | 持久化抽象 | Domain (端口) | 每个聚合一个,而非每个表 |
| 领域服务 | 无状态逻辑 | Domain | 当逻辑不适合放在实体中时 |
| 应用服务 | 编排 | Application | 协调领域和基础设施 |
| 反模式 | 问题 | 修复方法 |
|---|---|---|
| 贫血领域模型 | 实体是数据袋,逻辑在服务中 | 将行为移入实体内部 |
| 为每个实体创建仓储 | 破坏聚合边界 | 每个聚合一个仓储 |
| 基础设施泄漏 | Domain 层导入 DB/HTTP 库 | Domain 层应零外部依赖 |
| 上帝聚合 | 实体过多,事务缓慢 | 拆分为更小的聚合 |
| 跳过端口 | 控制器直接调用仓储 | 始终通过应用层 |
| CRUD 思维 | 建模数据,而非行为 | 对业务操作进行建模 |
| 过早引入 CQRS | 在需要之前增加复杂性 | 从简单的读写开始,逐步演进 |
| 跨聚合事务 | 在单个事务中包含多个聚合 | 使用领域事件实现一致性 |
DDD 是协作性的。 与领域专家一起进行建模会议,其重要性不亚于代码模式。
| 文件 | 用途 |
|---|---|
| references/LAYERS.md | 完整的层规范 |
| references/DDD-STRATEGIC.md | 限界上下文,上下文映射 |
| references/DDD-TACTICAL.md | 实体、值对象、聚合(伪代码) |
| references/HEXAGONAL.md | 端口、适配器、命名 |
| references/CQRS-EVENTS.md | 命令/查询分离,事件 |
| references/TESTING.md | 单元测试、集成测试、架构测试 |
| references/CHEATSHEET.md | 快速决策指南 |
每周安装量
961
代码仓库
GitHub 星标数
21
首次出现
Jan 21, 2026
安全审计
安装于
opencode863
gemini-cli847
codex841
github-copilot833
kimi-cli752
amp750
Backend architecture combining DDD tactical patterns, Clean Architecture dependency rules, and Hexagonal ports/adapters for maintainable, testable systems.
| 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.
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)
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 # 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
| 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 |
| 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 |
DDD is collaborative. Modeling sessions with domain experts are as important as the code patterns.
| 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 |
Weekly Installs
961
Repository
GitHub Stars
21
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode863
gemini-cli847
codex841
github-copilot833
kimi-cli752
amp750
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
| Stateless logic |
| Domain |
| When logic doesn't fit an entity |
| Application Service | Orchestration | Application | Coordinates domain + infra |
| Cross-Aggregate TX | Multiple aggregates in one transaction | Use domain events for consistency |
| Quick decision guide |