六边形架构
六边形架构围绕 7 个章专属概念,以边界模型、决策轨迹、违规恢复和来源分层完成验收。
学习目标
- 能解释“六边形架构”如何把应用核心与用户、测试、批处理、数据库和设备隔开,通过端口声明意图、适配器翻译技术协议
- 能逐项定位 系统内外、端口、适配器、驱动侧、被驱动侧、用户界面与数据库隔离、测试隔离,并说明每个概念在当前来源边界内承担什么责任
- 能按 识别外部参与者 → 定义输入端口 → 执行应用行为 → 调用输出端口 → 替换适配器测试 推演“无界面验收”,检查“应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义”
- 能注入“把六边形理解为必须存在六条边,或只把 Controller 改名 Adapter 而保留核心对框架的依赖”,依据端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本定位越界、撤销并用同一情境重放
为什么从“从应用与外部世界的交互意图识别端口,再为每种技术环境实现适配器,并让测试成为一等驱动者”开始
把应用核心与用户、测试、批处理、数据库和设备隔开,通过端口声明意图、适配器翻译技术协议。本页先画责任和依赖,再沿具体情境执行决策,最后主动制造一个边界违规;这种顺序把术语变成可以验证、推翻和恢复的设计合同。
“六边形架构”不是技术采购建议。它处理的是规则放在哪里、模型在哪个语境内成立、哪些变化可以被隔离,以及团队如何判断一条边界已经被穿透。最终功能可运行,只能证明快乐路径存在,不能证明结构允许安全演进。
来源、版次与课程边界
本单元是专题扩展,依据 Alistair Cockburn 2005 年原始 Hexagonal Architecture 文章;六边形只是避免上下分层偏见的视觉约定,不是边数要求。
本专题不是某一本既有书的中文版,也不是把多位作者的文章拼成“原著章节”。课程主干分别取自 Eric Evans 的领域驱动设计体系与 Robert C. Martin 的整洁架构体系;CQRS、事件溯源和六边形架构始终标为扩展。以下链接承担不同事实责任:
- Alistair Cockburn: Hexagonal Architecture:核对内外边界、端口、适配器、无 UI/数据库运行与自动化测试动机
本页采用独立中文重写。能从公开全文或授权摘要核对的定义才作为来源事实;项目情境、交互实验、取舍表和练习答案均为本站教学设计。
核心概念与可观察责任
系统内外
六边形架构首先区分应用内部与外部世界,不以传统上下层暗示数据库天然位于业务逻辑之下。 在“无界面验收”中,观察重点是应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义。
端口
端口是应用与外部交互的目的性接口,表达一类对话的协议;它属于应用边界,而不是具体技术连接器。 在“存储替换”中,观察重点是端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本。
适配器
适配器把 Web、命令行、测试、数据库或设备协议转换为端口语言,同一端口可以拥有多个技术实现。 在“无界面验收”中,观察重点是应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义。
驱动侧
用户、自动化测试、批处理或其他程序从驱动侧发起应用行为;它们通过输入端口表达意图。 在“存储替换”中,观察重点是端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本。
被驱动侧
应用通过输出端口请求持久化、通知或外部服务,被驱动适配器完成具体技术操作。 在“无界面验收”中,观察重点是应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义。
用户界面与数据库隔离
核心既不从界面控件读取业务输入,也不把数据库结构当领域模型;二者都可以独立更换和自动测试。 在“存储替换”中,观察重点是端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本。
测试隔离
测试适配器直接驱动端口并用内存适配器接管外部依赖,使应用逻辑在稳定、快速环境中完整运行。 在“无界面验收”中,观察重点是应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义。
一条可执行的设计判断
本页采用以下判断链:从应用与外部世界的交互意图识别端口,再为每种技术环境实现适配器,并让测试成为一等驱动者。正常情况下必须持续保持“应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义”;反例“把六边形理解为必须存在六条边,或只把 Controller 改名 Adapter 而保留核心对框架的依赖”只改变一个关键条件,便于定位因果。
| 观察项 | 本页合同 |
|---|---|
| 最小正常情境 | 用测试脚本直接提交借书请求并检查结果 |
| 边界或迁移情境 | 验收时用内存仓储,生产使用 SQL 仓储 |
| 必须保持 | 应用可以在没有真实用户界面和数据库时运行,外部技术通过端口接入而不改写内部业务语义 |
| 首要违规 | 把六边形理解为必须存在六条边,或只把 Controller 改名 Adapter 而保留核心对框架的依赖 |
| 验收证据 | 端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本 |
先预测,再操作三个本页实验
实验一:边界与模型地图
操作前先预测“无界面验收”里哪一侧拥有规则、哪一侧只是技术或协作细节。切换概念和情境后,检查“从应用与外部世界的交互意图识别端口,再为每种技术环境实现适配器,并让测试成为一等驱动者”是否仍能解释三块区域的责任。
Boundary model
六边形架构:边界与责任地图
把应用核心与用户、测试、批处理、数据库和设备隔开,通过端口声明意图、适配器翻译技术协议
切换最小情境
定位正式概念
architecturedomaindesign-11 · 当前观察
系统内外:用测试脚本直接提交借书请求并检查结果
Web、CLI、批处理与自动化测试
↓
业务用例及输入输出交互意图
↓
数据库、消息、设备与外部服务
情境验收
测试适配器驱动同一输入端口,不复制应用规则
易错边界与取舍
练习与答案
练习
问题 1:概念—边界—证据对照。 完成以下逐项核对:
- 系统内外:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 端口:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 适配器:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 驱动侧:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 被驱动侧:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 用户界面与数据库隔离:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
- 测试隔离:写出它所在的边界、允许的依赖方向、一个最小反例和一份可观察证据。
问题 2:最小情境推演。 怎样验证“无界面验收”没有靠最终功能碰巧通过?
问题 3:替代方案与恢复。 注入“把六边形理解为必须存在六条边,或只把 Controller 改名 Adapter 而保留核心对框架的依赖”后,怎样比较修复与更简单方案?
本页小结
- 六边形架构的核心判断是:从应用与外部世界的交互意图识别端口,再为每种技术环境实现适配器,并让测试成为一等驱动者。
- 正常路径以“测试适配器驱动同一输入端口,不复制应用规则”验收,不能只检查接口返回成功。
- 边界路径以“两个适配器满足同一输出端口合同,应用核心无需分支判断”验收,并保存端口清单、驱动与被驱动方向、适配器合同测试、无 UI 运行、内存存储替换与协议翻译样本。
- 如果“把六边形理解为必须存在六条边,或只把 Controller 改名 Adapter 而保留核心对框架的依赖”仍可静默通过,说明边界只是图示,没有成为可执行约束。