摘要
随着企业数字化业务持续迭代,多渠道接入、复杂业务规则变更的场景越来越普遍,传统以数据库、Web 页面为中心的分层架构,容易出现业务逻辑与外部基础设施强耦合的问题,业务代码难测试、改一动而牵全身。六边形架构(Hexagonal Architecture,又称端口 - 适配器架构)以领域核心为中心,通过端口定义内外交互契约,使用适配器隔离外部技术实现,强制依赖向内,实现业务逻辑与外部技术解耦。本文结合我所负责的工单管理平台项目,阐述六边形架构从领域分析、架构设计到落地开发的完整流程,介绍落地过程中的问题、解决方案以及架构落地后系统在可维护性、扩展性上的收益。
一、项目概述
我负责的项目是企业内部智眼工单管理平台,平台承载设备巡检、故障报修、工单分派、验收闭环全流程业务,对接移动端 APP、Web 后台、消息推送、物联网设备上报、第三方权限系统、数据库存储等多种外部接入端。 在架构改造前,系统采用传统三层架构,业务逻辑直接写在 Controller 与 Service 层中,大量代码直接依赖数据库、MQ、第三方接口。存在几个典型问题:
- 耦合严重:业务规则代码中混杂大量外部 API 调用、SQL 语句;切换消息中间件或者数据库时,需要大面积修改业务代码。
- 单元测试困难:业务代码强依赖外部中间件与数据库,编写单元测试必须启动数据库、MQ,测试成本高,业务规则很难独立验证。
- 多渠道适配成本高:新增接入渠道(如小程序)时,需要复制大量业务代码,渠道差异逻辑侵入核心业务。
我在项目中担任后端架构负责人,主导本次架构重构,引入六边形架构思想,完成领域模型梳理、端口抽象、适配器分层设计,带领开发团队落地改造。
二、六边形架构:从分析、设计到开发的全流程
2.1 核心概念
六边形架构核心思想:领域业务是系统的内核,所有外部系统都是外围,依赖必须指向内核,内核不依赖任何外部技术。
-
领域核心(Domain Core) 系统最中心,存放纯粹的业务实体、领域服务、业务规则。完全不依赖数据库、HTTP、消息队列等任何外部技术,只表达业务本身,没有任何基础设施代码。这部分代码是整个系统的 “业务真相”。
-
端口(Port) 端口是领域定义的交互契约(接口) ,分为入端口与出端口。
- 入端口:外部系统触发业务执行,例如创建工单、分派工单的业务接口,是外部调用领域能力的入口。
- 出端口:领域需要外部能力时,定义的抽象接口,比如 “保存工单”“推送通知”。领域只声明需要什么能力,不关心怎么实现。
-
适配器(Adapter) 适配器是端口的具体实现,位于六边形外围,负责转换技术协议。
- 入适配器:接收外部请求,转为领域入端口入参,例如 HTTP Controller、MQ 消费者。
- 出适配器:实现领域定义的出端口,调用外部基础设施,例如数据库仓储实现、消息发送客户端、第三方 API 调用。
依赖方向约束:适配器依赖领域(依赖向内);领域核心绝不依赖适配器和外部技术。领域只依赖自己定义的端口接口。
2.2 完整落地流程
- 领域分析阶段 用领域驱动思路梳理业务,识别业务实体、业务规则、业务边界,剥离技术细节,只关注业务本身,输出领域模型,区分 “业务逻辑” 和 “外部操作”。例如工单的状态流转、分派规则是业务;把工单存入数据库只是外部存储动作。
- 端口设计阶段 根据领域行为抽象端口。外部要调用业务能力 → 定义入端口;领域需要外部能力完成业务 → 定义出端口。端口只定义接口,不写实现。
- 适配器设计阶段 针对每个端口,按需实现不同适配器。例如 “保存工单” 这个出端口,可以实现 MySQL 适配器,也可以实现内存适配器(用于单元测试)。
- 开发与测试阶段 优先开发领域核心代码,基于端口编写单元测试,使用内存 Mock 适配器,不需要启动数据库。再实现外围适配器,适配器只做协议转换,不写业务规则。
- 集成验证 组装适配器,做集成测试,验证外部渠道与领域内核的交互。
三、六边形架构在工单平台项目的落地实践
3.1 架构设计落地
-
领域核心层 抽取工单实体
WorkOrder、领域服务WorkOrderDomainService,封装工单创建、状态流转、自动派单等业务规则。这一层代码没有任何 MyBatis、HTTP、MQ 相关 import,完全独立。 -
端口抽象
- 入端口:
WorkOrderCreatePort、WorkOrderAssignPort,定义创建工单、分派工单的业务方法。 - 出端口:
WorkOrderRepositoryPort(持久化)、NotifyPort(消息通知)、IotDeviceQueryPort(物联网设备查询)。领域服务调用这些端口接口,不关心底层实现。
- 入端口:
-
适配器实现
- 入适配器:Web Controller(HTTP 请求适配)、MQ 消费适配器(物联网设备上报事件适配),接收外部数据,调用入端口。
- 出适配器:
MysqlWorkOrderRepository实现仓储端口,RocketMQNotifyAdapter实现消息通知端口,第三方 HTTP 适配器实现设备查询端口。 单元测试时,直接写InMemoryWorkOrderRepository内存适配器,无需数据库,直接验证工单流转业务规则。
3.2 落地阻力与解决方案
-
阻力 1:开发习惯难以转变,容易把数据库逻辑写进领域 很多开发习惯在业务代码直接写查询、更新。
方案:制定代码检查规范,代码评审强制校验,领域包内禁止引入基础设施依赖;拆分包结构,领域包、端口包、适配器包物理隔离,借助静态代码扫描拦截违规引用。
-
阻力 2:短期开发工作量增加,抽象端口带来额外代码 相比老架构,需要额外定义接口、编写适配器,迭代初期开发速度变慢,团队有抵触。
方案:分阶段重构,不一次性重写全部模块。优先在新工单模块落地六边形,老模块逐步迁移;在单元测试收益上做示范,证明业务规则可以快速验证,减少线上业务逻辑 bug。
-
阻力 3:分层边界模糊,适配器中混入业务逻辑 部分开发者在 Controller / 适配器中增加业务判断,导致业务逻辑散落在外围。
方案:明确规约:所有业务规则必须放在领域内核,适配器只做数据转换、协议适配,不包含业务判断,代码评审重点检查。
3.3 架构带来的收益
- 可维护性提升 业务规则收敛在领域核心,查找业务逻辑不再需要在 Controller、SQL 中来回跳转;修改通知渠道、更换数据库时,只改动对应的适配器,核心业务代码完全不动。
- 单元测试能力大幅增强 业务单元测试使用内存适配器,无需依赖中间件,测试执行秒级完成,业务规则回归测试覆盖率显著提升,能够提前发现业务逻辑缺陷。
- 扩展性更强 新增接入渠道(如小程序工单入口),只需要新增一个入适配器,复用整套领域业务逻辑,不用重复开发工单流转规则;切换消息组件,仅替换 NotifyPort 对应的适配器实现。
四、总结
六边形架构的本质不是固定的代码包模板,而是向内依赖、隔离业务与外部技术的设计思想。它把业务领域作为系统的中心,通过端口建立抽象契约,利用适配器隔离外部技术细节。 在工单平台项目落地实践证明,六边形架构虽然在前期会增加一定抽象成本,但可以有效解决传统架构业务与技术耦合的痛点,提升业务代码可测试性,降低业务迭代、外部基础设施变更带来的风险。在业务规则复杂、需要多渠道接入、长期持续演进的企业应用场景下,六边形架构是非常合适的架构方案。