10 正交性

让组件的变化彼此独立,用边界、耦合证据和局部测试限制隐藏状态与时序假设的扩散。

学习目标

  • 能把“10 正交性”解释为职责、依赖、隔离、局部变化和影响验证的边界合同
  • 能用“提示17:消除不相关事物之间的影响”识别共享状态、时序假设、环境耦合和不必要的变化扩散
  • 能在真实项目中只改变一个组件,观察首个副作用,执行局部测试和恢复,并让独立复核者重放结论

为什么 10 正交性不是完全没有依赖

本页依据 David Thomas、Andrew Hunt《程序员修炼之道:通向务实的最高境界(第2版)》,云风译,电子工业出版社,2020年4月,ISBN 9787121384356 的公开完整中文目录,独立重构 10 正交性。本页不复制原书正文、插图、练习答案或代码,而把目录命题转写成边界合同、耦合矩阵、局部变化实验和复核证据。

系统不可能没有依赖。正交性要解决的是:当一个组件改变时,不相关组件是否被迫改变;共享的数据、控制、时间或环境假设是否让变化越过了应该停止的边界。必要的依赖可以通过协议、所有权和失败条件被看见;隐藏依赖则会让局部修订变成全局回归。

本单元把问题拆成 职责 → 依赖 → 隔离 → 局部变化 → 影响验证。每一步记录输入、输出、所有者、可接受的影响范围、拒绝条件和恢复动作,不把“测试通过”当作已经证明没有耦合。

10 正交性:边界合同

节点要问的问题可观察产物失败动作
职责组件负责什么,不负责什么输入、输出、owner 和不变量缩小职责或拆分命令与查询
依赖哪些数据、控制、时间和环境是必要的依赖方向与协议移除隐式全局状态
隔离变化在哪条边界停止Orthogonality Boundary 与耦合矩阵增加适配或消息边界
局部变化只改变一个实现会影响谁受影响节点和首个副作用停止扩散并恢复原状态
影响验证怎样证明无关组件未变局部测试、契约测试和回归补最早分叉的检查

Orthogonality Boundary 不是物理文件边界,而是变化责任和失败传播能被明确观察的边界。

Independent Axis 帮助团队把多个变化拆开;如果两条轴必须一起发布,应记录这个耦合而不是假装它们独立。

Coupling Matrix 让“这里有点耦合”变成可定位的节点、边和首个副作用。

Side Effect 可以是必要的,但必须有所有者、时机、失败处理和可测试的边界。

Local Test 不能替代端到端测试,但能帮助定位首个分叉,避免每次小修订都等待整个系统。

提示17:消除不相关事物之间的影响

提示17:消除不相关事物之间的影响。先把“相关”说清楚:如果两个组件共享同一领域不变量,它们可能需要通过协议协作;如果只是碰巧读取同一全局配置或依赖某个调用顺序,就不应让一方的内部变化影响另一方。

检查四类泄漏:数据泄漏指内部结构被外部直接修改;控制泄漏指调用者必须知道内部步骤;时间泄漏指结果依赖未声明的先后顺序;环境泄漏指测试或生产的全局状态改变了组件行为。每一种泄漏都应在 Coupling Matrix 中有边、有 owner、有失败证据。

从命题到可失败的因果链

本页主链是 职责 → 依赖 → Orthogonality Boundary → 局部变化 → Local Test。每条边要写明传递的是数据、控制、时间、环境还是反馈;每个节点要有输入、输出、接受条件、拒绝动作和恢复路径。只有把“正交”写在标题中而没有变化实验,不能证明它成立。

先写预测,再执行正常样本、边界样本和一次故障样本。三类样本共享项目版本、输入和观察窗口,只改变一个 Independent Axis 或一个依赖条件;结果出现差异时记录首个 Side Effect,不用最终红灯覆盖前面的分叉。

10 正交性:让依赖类型和边界可见OrthogonalityBoundary数据 / 控制时间 / 环境Coupling Matrix谁依赖谁依赖什么 / 谁负责首个副作用在哪里影响类型必要协议隐藏状态 / 时序不相关扩散提示17:边界让必要协作留下,不相关影响停下矩阵把模糊的耦合争论变成可定位的依赖
正交性不是没有边,而是每条边都有方向、类型和所有者。

读懂耦合矩阵

矩阵的每一格都回答“谁依赖谁、依赖什么、谁负责解除”。数据依赖可以通过稳定 DTO 或查询接口隔离,控制依赖可以通过命令和结果协议隔离,时间依赖可以通过显式状态或消息确认隔离,环境依赖可以通过注入配置和独立测试隔离。

矩阵不是越空越好。若支付服务必须知道订单金额,这是声明的业务依赖;若支付服务必须知道通知模块刚刚完成了哪一步,且没有协议说明,则是隐藏的时间耦合。用同一变化请求逐格检查,能区分必要协作与不相关扩散。

局部变化与首个副作用

选择一条 Independent Axis,例如替换通知供应商,只改适配器实现。先预测业务规则、结算和用户结果不应变化,再运行 Local Test、契约测试和低风险端到端演练。若出现共享缓存、全局配置或顺序相关的 Side Effect,停在第一个受影响节点,保存输入、状态和调用轨迹。

10 正交性:一次局部变化,定位首个副作用Independent Axis只替换适配器其他输入不变Local Test协议 / 错误映射正常 / 乱序 / 超时首个 Side Effect全局状态 / 时序停止扩大实验修复隔离重放跨边界就回退:先修依赖,再扩大验证局部测试帮助定位首差,回归测试确认影响被隔离
单变量实验把正交性从口号变成首个副作用和恢复证据。

恢复时先回到原始状态,解除泄漏的依赖,再重放相同样本。修复后的测试应证明“变化停在边界”,而不是只证明当前样本最后返回了成功。

三步完成一次正交性检查

分步1 / 3

先声明职责与独立轴

为目标组件写清输入、输出、不变量、owner 和不负责的事情,选择一条 Independent Axis。用 Coupling Matrix 标出数据、控制、时间和环境依赖,并标记哪些关系是必要的。

10 正交性:让依赖类型和边界可见OrthogonalityBoundary数据 / 控制时间 / 环境Coupling Matrix谁依赖谁依赖什么 / 谁负责首个副作用在哪里影响类型必要协议隐藏状态 / 时序不相关扩散提示17:边界让必要协作留下,不相关影响停下矩阵把模糊的耦合争论变成可定位的依赖
正交性不是没有边,而是每条边都有方向、类型和所有者。

可重放的正交性记录

orthogonality_record:
  unit: tpp20-topic-10-orthogonality
  independent_axis: 通知供应商适配器
  responsibility: 接收通知命令并返回投递结果
  declared_boundary: 业务规则只依赖 NotificationPort
  coupling_matrix: 数据、控制、时间、环境四类依赖均有 owner
  local_test: 适配器错误映射与重试策略测试
  injected_change: 只替换供应商 SDK
  first_side_effect: 全局重试计数改变结算超时
  recovery: 注入重试策略并恢复隔离的计数器
  proof: 局部、契约、集成和用户结果检查全部重放

这份记录把“无关事物不受影响”变成可重建证据。若 Local Test 通过但结算超时改变,说明局部测试覆盖不足;若全局计数器确实属于共同业务不变量,则应把它写入协议,而不是把它伪装成不存在的依赖。

选择、拒绝与迁移矩阵

判断接受证据应拒绝的信号
职责输入、输出、不变量和 owner 清楚组件可以修改所有共享状态
数据依赖通过稳定协议传递并校验外部直接读取内部结构
控制依赖命令、结果和失败动作明确调用者必须记住内部顺序
时间依赖时序由状态、确认或消息声明“通常先调用 A”却无检查
环境依赖配置注入且测试可隔离全局变量决定测试结果
影响验证首个副作用可定位并有局部测试只有整套回归最后变红

迁移到云服务、数据系统或 AI 辅助开发时,分别记录线程、缓存、配置、权限和自动化反馈。工具可以生成依赖图或测试,但仍需人判断某条边是必要业务协作还是不相关影响。

常见误区

本章回顾

掌握 10 正交性,不是消灭所有依赖,而是让必要依赖有边界、方向、所有者和失败合同,让不相关变化停在局部。按 提示17:消除不相关事物之间的影响 识别数据、控制、时间和环境泄漏,用 Coupling Matrix 预测扩散,再用 Local Test 和首个 Side Effect 证据证明恢复后的变化确实被隔离。

可验证练习

练习

本组练习覆盖 10 正交性提示17:消除不相关事物之间的影响,要求提交 Orthogonality Boundary、Independent Axis、Coupling Matrix、Side Effect 和 Local Test 的证据。

问题 1: 替换通知供应商后,订单结算偶尔超时。如何使用 Coupling Matrix 定位不相关影响?

问题 2: 如何实践“提示17:消除不相关事物之间的影响”,而不是复制所有依赖?

问题 3: 怎样设计局部测试来捕获隐藏的时序耦合?

名词解释

名词解释

本章出现的专业名词,用大白话再讲一遍。

Orthogonality Boundary

定义数据、控制、时间和环境可见范围的变化与失败边界。

Independent Axis

可以独立改变、测试和回滚的一条变化方向。

Coupling Matrix

记录组件之间依赖类型、方向、强度和所有权的对照表。

Side Effect

组件在声明输出之外改变的状态、调用、顺序或外部资源。

Local Test

在较短反馈路径中验证一个组件、协议或边界行为的检查。

前后导航

来源与改写范围

讨论

评论区加载中…