ddd-architecture-hexagonal
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDDD Architecture — Hexagonal (Ports & Adapters)
DDD Architecture — Hexagonal (Ports & Adapters)
Alistair Cockburn (2005) — 业务逻辑通过端口(Ports)隔离,外部系统通过适配器(Adapters)接入。适用受众: 后端架构师/技术负责人(团队 > 5 人)、DDD 实践者。定制机制: 提供技术栈/入口类型/团队规模三个配置维度。加载本技能时,建议先阅读 Workflow 和 When to Use 确认匹配度。
"允许应用被用户、程序、自动化测试或批处理脚本平等驱动,并在脱离最终运行设备和数据库的情况下开发和测试。" — Alistair Cockburn
Alistair Cockburn (2005) — Business logic is isolated through Ports, while external systems are integrated through Adapters. Target audience: backend architects/technical leads (teams > 5 people), and DDD practitioners. Customization mechanism: Three configuration dimensions are provided: technology stack, entry-point type, and team size. When loading this skill, you are recommended to first read Workflow and When to Use to confirm that it is a suitable match.
"Allow an application to be equally driven by users, programs, automated tests, or batch scripts, and to be developed and tested in isolation from its final runtime devices and database." — Alistair Cockburn
Workflow
Workflow
Step 1: 主适配器协议转换 — REST Controller/CLI 接收请求,完成参数校验与协议转换
Step 1: Primary Adapter protocol conversion — The REST Controller/CLI receives the request, performs parameter validation, and converts the protocol
Step 2: 入站端口调用 — 适配器调用 UseCase 接口,触发应用层用例编排
Step 2: Inbound port invocation — The Adapter invokes the UseCase interface, triggering use-case orchestration in the application layer
Step 3: 应用服务编排 — Application Service 编排用例,调用领域模型执行业务逻辑
Step 3: Application service orchestration — The Application Service orchestrates the use case and invokes the domain model to execute business logic
Step 4: 领域模型执行 — 聚合根/实体执行业务逻辑,输出结果或领域事件
Step 4: Domain model execution — The aggregate root/entity executes business logic and outputs a result or domain events
Step 5: 出站端口持久化 — 应用服务通过 Repository 接口保存领域状态
Step 5: Outbound port persistence — The Application Service persists domain state through the Repository interface
Step 6: 次适配器技术实现 — Adapter 执行 DB/MQ/外部 API 的技术实现
Step 6: Secondary Adapter technical implementation — The Adapter provides the technical implementation for DB/MQ/external API integrations
定义验证法: 脱离数据库和 HTTP 即可跑通全部领域层单元测试 → 边界正确。
Boundary validation method: All domain-layer unit tests can pass without a database or HTTP → the boundaries are correct.
Rules
Rules
- 依赖规则: 依赖方向必须从外到内——Adapter → Application → Domain。Domain 层零外部依赖。
- 端口粒度规则: 每个端口职责单一,包含 10+ 方法的端口需立即拆分。
- 异常转换规则: 技术异常(SQLException、TimeoutException)必须在 Adapter 内部捕获并转换为领域异常,不得向上泄漏。
- Dependency rule: The dependency direction must be from outside to inside—Adapter → Application → Domain. The Domain layer must have zero external dependencies.
- Port granularity rule: Each port must have a single responsibility. Any port containing 10+ methods must be split immediately.
- Exception translation rule: Technical exceptions (SQLException, TimeoutException) must be caught inside the Adapter and translated into domain exceptions; they must not leak upward.
When to Use
When to Use
✅ 适合场景
✅ Suitable Scenarios
- 多入口系统(REST + CLI + MQ + gRPC):多个外部系统同时驱动同一业务逻辑
- 基础设施频繁变更(换 DB/MQ/缓存):只需换 Adapter 实现,Domain 零修改
- 极致可测试性:Mock 端口即可测试全部领域逻辑,不依赖数据库
- 微服务架构标准化:团队 > 5 人,需要各服务一致的架构约定
- 团队熟悉抽象设计:能合理设计端口粒度,避免过度抽象
- Multi-entry-point systems (REST + CLI + MQ + gRPC): multiple external systems drive the same business logic simultaneously
- Frequently changing infrastructure (switching DB/MQ/cache): only the Adapter implementation changes, with no modifications to the Domain
- Maximum testability: Mock the ports to test all domain logic without depending on a database
- Standardizing microservice architecture: teams > 5 people need consistent architectural conventions across services
- The team is familiar with abstract design: it can reasonably define port granularity and avoid over-abstraction
Boundary
Boundary
⚠️ 需要条件
⚠️ Conditions Required
- 团队理解抽象设计:端口粒度需要领域知识和抽象能力,否则可能定义不当
- 项目规模适中:小项目用 Layered 更简单,六边形增加间接层成本
- 需要 DDD 领域模型配合:Port 接口定义需要领域建模前置知识
- 良好的 DI 容器支持:Spring/Guice 等框架可简化适配器装配
- The team understands abstract design: defining port granularity requires domain knowledge and abstraction skills; otherwise, the ports may be defined incorrectly
- The project is of moderate size: Layered Architecture is simpler for small projects, while Hexagonal Architecture adds the cost of indirection layers
- A DDD domain model is required: defining Port interfaces presupposes knowledge of domain modeling
- Good DI container support: frameworks such as Spring and Guice can simplify adapter wiring
❌ 不适用(附替代方案)
❌ Not Applicable (with Alternatives)
- 单一 REST API + 简单 CRUD → 用
ddd-architecture-layered - 中文企业 MyBatis 生态 → 用
ddd-architecture-cola - 需 UseCase + Entity 严格分离 → 用
ddd-architecture-clean - 快速原型 / MVP 阶段 → 直接用传统三层(不引入六边形架构的开销)
- Single REST API + simple CRUD → use
ddd-architecture-layered - Enterprise MyBatis ecosystem in China → use
ddd-architecture-cola - Strict UseCase + Entity separation is required → use
ddd-architecture-clean - Rapid prototyping / MVP stage → use a traditional three-tier architecture directly, without the overhead of Hexagonal Architecture
核心原理
Core Principles
三大抽象
Three Abstractions
Driving Side (REST/CLI/gRPC/Test) → Domain Core ← Driven Side (PostgreSQL/RabbitMQ/Redis/Stripe)| 概念 | 说明 | 代码体现 |
|---|---|---|
| Port(端口) | 领域层定义的接口 | |
| Primary Adapter(主适配器) | 外部如何驱动系统 | REST Controller、CLI Command、gRPC Service |
| Secondary Adapter(次适配器) | 系统如何驱动外部 | JPA RepositoryImpl、Kafka Producer、StripeClient |
Driving Side (REST/CLI/gRPC/Test) → Domain Core ← Driven Side (PostgreSQL/RabbitMQ/Redis/Stripe)| Concept | Description | Code Representation |
|---|---|---|
| Port | An interface defined in the Domain layer | |
| Primary Adapter | How external actors drive the system | REST Controller, CLI Command, gRPC Service |
| Secondary Adapter | How the system drives external systems | JPA RepositoryImpl, Kafka Producer, StripeClient |
Strong Port vs Weak Port
Strong Port vs Weak Port
java
// ❌ Weak — 泄漏 SQL 概念
interface OrderRepository { List<Order> findByQuery(String sql, Map<String, Object> params); }
// ✅ Strong — 纯领域概念
interface OrderRepository {
Optional<Order> findById(OrderId id);
List<Order> findByCustomerId(CustomerId customerId);
void save(Order order);
}java
// ❌ Weak — 泄漏 SQL 概念
interface OrderRepository { List<Order> findByQuery(String sql, Map<String, Object> params); }
// ✅ Strong — 纯领域概念
interface OrderRepository {
Optional<Order> findById(OrderId id);
List<Order> findByCustomerId(CustomerId customerId);
void save(Order order);
}目录结构
Directory Structure
{project}/
├── {project}-domain/ # 领域核心 + 端口定义(零框架依赖)
│ └── port/{inbound, outbound}/ # ★ 端口接口
├── {project}-application/ # 应用层(UseCase 实现)
├── {project}-adapter/ # 适配器层
│ ├── inbound/ # ★ 主适配器(REST/CLI/gRPC/MQ)
│ └── outbound/ # ★ 次适配器(Persistence/Messaging/External)
└── {project}-configuration/ # 配置层(DI 装配){project}/
├── {project}-domain/ # 领域核心 + 端口定义(零框架依赖)
│ └── port/{inbound, outbound}/ # ★ 端口接口
├── {project}-application/ # 应用层(UseCase 实现)
├── {project}-adapter/ # 适配器层
│ ├── inbound/ # ★ 主适配器(REST/CLI/gRPC/MQ)
│ └── outbound/ # ★ 次适配器(Persistence/Messaging/External)
└── {project}-configuration/ # 配置层(DI 装配)开发规范
Development Standards
层职责
Layer Responsibilities
| 层 | 依赖 | 允许做的事 | 禁止做的事 |
|---|---|---|---|
| Domain | 无 | 实体行为、值对象、领域事件、端口定义 | import 框架注解、SQL、HTTP |
| Application | Domain | 用例编排、事务管理、端口调用 | if/else 业务判断、直接操作 DB |
| Adapter | Application | 协议转换、参数校验、异常映射 | 包含业务逻辑、直接操作 Domain 内部状态 |
| Configuration | 全部 | DI 装配、Profile 配置 | 包含业务代码 |
| Layer | Depends On | Allowed Responsibilities | Prohibited Responsibilities |
|---|---|---|---|
| Domain | None | Entity behavior, value objects, domain events, port definitions | Importing framework annotations, SQL, or HTTP |
| Application | Domain | Use-case orchestration, transaction management, port invocation | if/else business decisions, direct DB operations |
| Adapter | Application | Protocol conversion, parameter validation, exception mapping | Including business logic, directly manipulating internal Domain state |
| Configuration | All | DI wiring, Profile configuration | Including business code |
代码规范
Code Standards
java
// 入站端口(Domain)
public interface CreateOrderUseCase { OrderCreatedResult execute(CreateOrderCommand command); }
// 出站端口(Domain)
public interface OrderRepository { void save(Order order); Optional<Order> findById(OrderId id); }
// 应用服务(实现入站端口,注入出站端口)
@ApplicationService
public class CreateOrderService implements CreateOrderUseCase {
private final OrderRepository orderRepository;
@Override @Transactional
public OrderCreatedResult execute(CreateOrderCommand command) {
Order order = Order.create(command.getCustomerId());
orderRepository.save(order);
return OrderCreatedResult.from(order);
}
}
// 主适配器(仅协议转换)
@RestController
public class OrderController {
@PostMapping("/orders")
public ResponseEntity<CreateOrderResponse> create(@RequestBody @Valid CreateOrderRequest req) {
var result = createOrderUseCase.execute(req.toCommand());
return ResponseEntity.status(201).body(CreateOrderResponse.from(result));
}
}
// 次适配器(技术实现)
@Repository
public class PostgresOrderRepository implements OrderRepository {
@Override public void save(Order order) { jpaRepo.save(mapper.toPO(order)); }
}java
// 入站端口(Domain)
public interface CreateOrderUseCase { OrderCreatedResult execute(CreateOrderCommand command); }
// 出站端口(Domain)
public interface OrderRepository { void save(Order order); Optional<Order> findById(OrderId id); }
// 应用服务(实现入站端口,注入出站端口)
@ApplicationService
public class CreateOrderService implements CreateOrderUseCase {
private final OrderRepository orderRepository;
@Override @Transactional
public OrderCreatedResult execute(CreateOrderCommand command) {
Order order = Order.create(command.getCustomerId());
orderRepository.save(order);
return OrderCreatedResult.from(order);
}
}
// 主适配器(仅协议转换)
@RestController
public class OrderController {
@PostMapping("/orders")
public ResponseEntity<CreateOrderResponse> create(@RequestBody @Valid CreateOrderRequest req) {
var result = createOrderUseCase.execute(req.toCommand());
return ResponseEntity.status(201).body(CreateOrderResponse.from(result));
}
}
// 次适配器(技术实现)
@Repository
public class PostgresOrderRepository implements OrderRepository {
@Override public void save(Order order) { jpaRepo.save(mapper.toPO(order)); }
}落地步骤
Implementation Steps
Phase 1: 定义端口(1-2 天)→ 入站端口(UseCase) → 出站端口(Repository/Gateway)
Phase 2: 领域模型(2-3 天)→ 聚合根/实体/值对象 → 领域服务 → 领域事件
Phase 3: 应用服务(1-2 天)→ UseCase 实现(注入端口,编排调用)
Phase 4: 适配器(2-4 天) → 主适配器(REST/gRPC/CLI) → 次适配器(DB/MQ/External)
Phase 5: DI 装配 + 测试(1-2 天)→ DI 配置 → 端口 Mock 测试 → 适配器集成测试Phase 1: 定义端口(1-2 天)→ 入站端口(UseCase) → 出站端口(Repository/Gateway)
Phase 2: 领域模型(2-3 天)→ 聚合根/实体/值对象 → 领域服务 → 领域事件
Phase 3: 应用服务(1-2 天)→ UseCase 实现(注入端口,编排调用)
Phase 4: 适配器(2-4 天) → 主适配器(REST/gRPC/CLI) → 次适配器(DB/MQ/External)
Phase 5: DI 装配 + 测试(1-2 天)→ DI 配置 → 端口 Mock 测试 → 适配器集成测试Security & Stability
Security & Stability
- 本技能为纯文档型架构指南,不收集、不处理、不上传用户数据。
- 所有代码模板均为教学参考。替换外部服务 URL、密钥和凭证为环境变量配置。
- Port/Adapter 隔离确保领域逻辑不直接依赖 HTTP/DB/MQ 库——Adapter 层处理所有 I/O。
- 实现 Secondary Adapter 时,始终设置连接/读取超时,对关键路径实现断路器模式。
- This skill is a documentation-only architecture guide and does not collect, process, or upload user data.
- All code templates are provided for educational reference. Replace external service URLs, secrets, and credentials with environment-variable-based configuration.
- Port/Adapter isolation ensures that domain logic does not directly depend on HTTP/DB/MQ libraries—the Adapter layer handles all I/O.
- When implementing a Secondary Adapter, always configure connection/read timeouts and implement the circuit breaker pattern for critical paths.
Gotchas(8 条常见陷阱)
Gotchas (8 Common Pitfalls)
- 端口定义过宽: 每个端口只做一件事。包含 10+ 方法的端口视为"上帝端口",立即拆分。
- 主适配器包含业务逻辑: Controller 只能做参数转换和调用 UseCase,不能包含 if/else 业务判断。
- 次适配器忘记异常转换: 技术异常(SQLException、TimeoutException)必须在适配器内部转换为领域异常。
- 领域层框架依赖: Domain 模块不能 import Spring/JPA/MyBatis 注解。
- 端口命名不一致: 入站端口用动作命名(),出站端口用资源命名(
CreateOrderUseCase)。OrderRepository - 事务放在适配器层: 事务由应用层控制,适配器不负责事务管理。
- 过度抽象: 不为"未来可能会换"提前创建端口。等真正需要替换时再抽取端口。
- 用户需求不清晰时先给假设: 用户没说技术栈/入口类型/团队规模时,先给假设版本再补充提问。
- Port definition is too broad: Each port should do only one thing. A port containing 10+ methods is considered a “god port” and must be split immediately.
- The Primary Adapter contains business logic: A Controller may only convert parameters and invoke the UseCase; it must not contain if/else business decisions.
- The Secondary Adapter forgets exception translation: Technical exceptions (SQLException, TimeoutException) must be translated into domain exceptions inside the Adapter.
- The Domain layer has framework dependencies: The Domain module must not import Spring/JPA/MyBatis annotations.
- Inconsistent port naming: Name inbound ports using actions () and outbound ports using resources (
CreateOrderUseCase).OrderRepository - Transactions are placed in the Adapter layer: Transactions are controlled by the application layer; Adapters must not manage them.
- Over-abstraction: Do not create ports in advance for something that “might be replaced in the future.” Extract a port only when replacement is actually needed.
- State assumptions first when user requirements are unclear: If the user has not specified the technology stack, entry-point type, or team size, provide an assumed version first and then ask follow-up questions.
FAQ(8 条常见问题)
FAQ (8 Common Questions)
Q1: 六边形和整洁架构有什么区别? A: 六边形由 Cockburn 提出(2005),核心是端口/适配器;整洁由 Uncle Bob 提出(2012),强调 UseCase 和 Entity 分离。六边形更关注"对称性"(主/次适配器),整洁更关注"依赖规则"。
Q2: 端口应该放在 Domain 层还是 Application 层? A: 推荐放在 Domain 层。Domain 是业务核心,端口是业务对外部依赖的抽象。
Q3: 如何避免端口过度抽象? A: YAGNI 原则:只为当前确定的变更需求定义端口。
Q4: 一个 UseCase 接口一个方法还是多个方法? A: 推荐一个接口一个方法(接口隔离原则)。但高度相关的方法(如 OrderRepository 的 save/findById)可放同一接口。
Q5: Controller 层的 DTO 和 Domain 层的 Entity 能否共用? A: 不能。DTO 是适配器层的数据载体,Entity 是领域层的业务模型,需要 Mapper 转换。
Q6: 六边形架构如何处理查询? A: 查询也通过端口进行。使用 返回只读 DTO,复杂查询可用 CQRS。
Q7: 如何验证六边形边界是否正确? A: 能否不启动数据库和 HTTP 就跑通 Domain 层全部单元测试?能 → 正确。不能 → 有泄漏。
Q8: 团队不熟悉六边形架构怎么办? A: 逐步引入。先做好 Domain 层纯净度和端口定义,再逐步抽取适配器。
QueryOrderUseCaseQ1: What is the difference between Hexagonal Architecture and Clean Architecture? A: Hexagonal Architecture was proposed by Cockburn (2005) and centers on ports and adapters. Clean Architecture was proposed by Uncle Bob (2012) and emphasizes the separation of UseCase and Entity. Hexagonal Architecture focuses more on “symmetry” between primary and secondary adapters, while Clean Architecture focuses more on the dependency rule.
Q2: Should ports be placed in the Domain layer or the Application layer? A: The Domain layer is recommended. The Domain is the core of the business, and ports are abstractions of the business's external dependencies.
Q3: How can over-abstraction of ports be avoided? A: Follow the YAGNI principle: define ports only for currently confirmed change requirements.
Q4: Should a UseCase interface contain one method or multiple methods? A: Prefer one method per interface, following the Interface Segregation Principle. However, closely related methods, such as and in , may belong in the same interface.
Q5: Can DTOs in the Controller layer and Entities in the Domain layer be shared? A: No. A DTO is a data carrier in the Adapter layer, while an Entity is the business model in the Domain layer. A Mapper is required to convert between them.
Q6: How does Hexagonal Architecture handle queries? A: Queries also go through ports. Use to return a read-only DTO; complex queries can use CQRS.
Q7: How can the correctness of Hexagonal Architecture boundaries be verified? A: Can all Domain-layer unit tests run without starting a database or HTTP server? If yes, the boundaries are correct. If not, there is a leakage.
Q8: What should a team do if it is unfamiliar with Hexagonal Architecture? A: Introduce it incrementally. First ensure the purity of the Domain layer and define the ports properly, then progressively extract the Adapters.
savefindByIdOrderRepositoryQueryOrderUseCaseReferences
References
| 文件 | 目的 |
|---|---|
| references/01-port-definitions.md | 端口定义规范 — 入站/出站端口、命名、粒度、Strong/Weak |
| references/02-primary-adapters.md | 主适配器详解 — REST/CLI/gRPC/MQ 四种适配器实现 |
| references/03-secondary-adapters.md | 次适配器详解 — JPA/MyBatis/Stripe/RabbitMQ/InMemory |
| references/04-domain-model.md | 领域模型设计 — 聚合根、实体、值对象、领域服务、领域事件 |
| references/05-application-services.md | 应用服务层 — UseCase 实现、编排规范、命令对象 |
| references/06-di-configuration.md | DI 配置 — Spring Config、Profile 切换、多环境适配器 |
| references/07-testing.md | 测试策略 — 领域层/应用层/适配器/架构 四级测试 |
| references/08-migration.md | 渐进迁移 — 从传统三层到六边形的迁移指南 |
| examples/01-order-hexagonal-complete.md | 完整订单六边形示例 — Domain/Port/Service/Adapter 全流程 |
| examples/02-user-registration-example.md | 用户注册示例 — 值对象、验证码、领域事件 |
| examples/03-multi-entry-points-example.md | 多入口系统示例 — 同一 UseCase 供 REST/CLI/Kafka/gRPC 调用 |
| examples/04-adapter-swapping-example.md | 适配器可替换性示例 — Postgres→MongoDB、Stripe→PayPal 零代码修改 |
| examples/05-port-swapping-test.md | 主适配器可替换性示例 — REST/gRPC/CLI 三种入口 + 端口级测试 |
| examples/06-monolith-simple.md | 单体简单六边形 — 单模块四包 + ports/adapters 子包结构 |
| examples/07-monolith-complex.md | 单体复杂六边形 — 多端口 + 多适配器 + 多聚合根 |
| examples/08-monolith-multi-module.md | 单体多模块六边形 — Maven 多模块编译期边界约束 |
| examples/09-microservice-simple.md | 微服务简单六边形 — 单微服务内最小六边形结构 |
| examples/10-microservice-complex.md | 微服务复杂六边形 — 多聚合 + Saga + 跨服务调用 |
| examples/11-microservice-multi-module.md | 微服务多模块六边形 — 每服务内部 Maven 多模块 |
| examples/12-microservice-complex-multi.md | 微服务复杂多模块 — CQRS + 读写分离 + CDC + 分布式 Saga |
| File | Purpose |
|---|---|
| references/01-port-definitions.md | Port definition standards — inbound/outbound ports, naming, granularity, Strong/Weak |
| references/02-primary-adapters.md | Primary Adapter details — four adapter implementations: REST/CLI/gRPC/MQ |
| references/03-secondary-adapters.md | Secondary Adapter details — JPA/MyBatis/Stripe/RabbitMQ/InMemory |
| references/04-domain-model.md | Domain model design — aggregate roots, entities, value objects, domain services, domain events |
| references/05-application-services.md | Application service layer — UseCase implementation, orchestration standards, command objects |
| references/06-di-configuration.md | DI configuration — Spring Config, Profile switching, multi-environment adapters |
| references/07-testing.md | Testing strategy — four testing levels: domain/application/adapter/architecture |
| references/08-migration.md | Progressive migration — migration guide from traditional three-tier architecture to Hexagonal Architecture |
| examples/01-order-hexagonal-complete.md | Complete order Hexagonal example — end-to-end Domain/Port/Service/Adapter flow |
| examples/02-user-registration-example.md | User registration example — value objects, verification codes, domain events |
| examples/03-multi-entry-points-example.md | Multi-entry-point system example — the same UseCase invoked by REST/CLI/Kafka/gRPC |
| examples/04-adapter-swapping-example.md | Adapter swappability example — Postgres→MongoDB and Stripe→PayPal with no code changes |
| examples/05-port-swapping-test.md | Primary Adapter swappability example — three entry types: REST/gRPC/CLI, plus port-level testing |
| examples/06-monolith-simple.md | Simple monolith in Hexagonal style — four packages in one module, with ports/adapters subpackages |
| examples/07-monolith-complex.md | Complex monolith in Hexagonal style — multiple ports, adapters, and aggregate roots |
| examples/08-monolith-multi-module.md | Monolith with multiple modules — Maven multi-module compile-time boundary constraints |
| examples/09-microservice-simple.md | Simple microservice in Hexagonal style — minimal Hexagonal structure within one microservice |
| examples/10-microservice-complex.md | Complex microservice in Hexagonal style — multiple aggregates, Saga, and cross-service calls |
| examples/11-microservice-multi-module.md | Microservice with multiple modules — Maven multi-module setup within each service |
| examples/12-microservice-complex-multi.md | Complex microservice with multiple modules — CQRS, read/write separation, CDC, and distributed Saga |
Primary Sources
Primary Sources
- Hexagonal Architecture — Alistair Cockburn (2005)
- Hexagonal Architecture Explained — Cockburn & Garrido de Paz (2024)
- Domain-Driven Design: The Blue Book — Eric Evans (2003)
- AWS: Hexagonal Architecture Pattern
- Hexagonal Architecture — Alistair Cockburn (2005)
- Hexagonal Architecture Explained — Cockburn & Garrido de Paz (2024)
- Domain-Driven Design: The Blue Book — Eric Evans (2003)
- AWS: Hexagonal Architecture Pattern
导航
Navigation
- → Next: hand off to the skill — 为六边形架构设计领域模型。Install:
ddd-domain-designer.npx skills add full-stack-skills/ddd-skills --skill ddd-domain-designer - 🔗 Related: — 端口 Mock 测试(Install:
ddd-testing-strategist) |npx skills add full-stack-skills/ddd-skills --skill ddd-testing-strategist— 六边形 API 设计(Install:ddd-api-designer).npx skills add full-stack-skills/ddd-skills --skill ddd-api-designer
💡 六边形 = 端口 + 适配器。验证法:不启动数据库和 HTTP,只跑 CLI/单元测试就能执行业务逻辑 → 边界正确。
- → Next: Hand off to the skill — design domain models for Hexagonal Architecture. Install:
ddd-domain-designer.npx skills add full-stack-skills/ddd-skills --skill ddd-domain-designer - 🔗 Related: — Port Mock testing (Install:
ddd-testing-strategist) |npx skills add full-stack-skills/ddd-skills --skill ddd-testing-strategist— Hexagonal API design (Install:ddd-api-designer).npx skills add full-stack-skills/ddd-skills --skill ddd-api-designer
💡 Hexagonal Architecture = Ports + Adapters. Validation method: Run business logic through CLI/unit tests without starting a database or HTTP server → the boundaries are correct.