适应度函数

把架构特征写成可自动验证的检查:性能预算、依赖方向、模块耦合度、安全基线;在流水线持续执行,架构约束不再依赖口头约定。

什么是适应度函数

适应度函数(Fitness Function)指把架构约束写成可自动执行的检查:性能预算、依赖方向、循环依赖、接口兼容、安全基线都能被翻译成断言。它要解决的问题是架构约定只写在文档里、实现随迭代慢慢漂移。福特等人在《演进式架构》中把它作为守护架构方向的核心机制:约束可执行,架构才可演进。

基本信息

概念出处《演进式架构》(Ford、Parsons、Kua)
常见形态单元测试、静态依赖分析、度量脚本、配置扫描
执行时机提交钩子、合并流水线、每日构建
必备属性客观可复现、阈值明确、失败有归属人

典型使用场景

  • 分层约束:禁止领域层引用基础设施包,用静态分析在构建期直接失败
  • 性能护栏:把接口 P99 预算写成基准对比,回归超阈值即告警或阻断
  • 契约守护:接口变更用规范差异工具比对,破坏性修改按版本策略拒绝
  • 数据边界:检查服务是否直接连了别人的库,阻断共享库式的隐性耦合
  • 安全基线:配置与依赖漏洞扫描纳入流水线,高危项不允许合入
  • 运维约束:镜像基础版本、日志字段、健康检查端点是否统一

检查项与失败处置

检查项示例工具失败处置
依赖方向ArchUnit、dependency-cruiser构建失败,阻止合入
循环依赖madge、deptrac阻断合并并要求拆分
性能预算k6 与基线对比超阈值告警并定位提交
接口兼容openapi-diff、buf breaking按版本策略拒绝变更
安全基线依赖与配置扫描高危项阻断,中危转工单

流水线中的一种写法

流水线中的一种写法
# 1) 快速检查跑在每次提交:依赖方向与循环依赖,秒级返回
npx dependency-cruiser --validate .dependency-cruiser.js src/   # 违规即非零退出
# 2) 慢检查跑在每日构建:性能预算与契约比对
k6 run --out json=bench.json perf/order-p99.js   # 生成基准数据
python tools/compare_budget.py bench.json baseline.json   # 超预算退出码 1
# 3) 失败时把指标与提交号一起留档,便于定位是哪次改动引入的回归
echo "fitness check failed: see artifacts/fitness-report.json"
阈值过渡要现实:新引入的检查若历史违规一大堆,先设基线并只拦新增违规,等清零后再改为全量阻断。
适应度函数要控制数量与粒度:一次引入十几项强制检查会被团队绕过或长期豁免,按风险优先级逐个落地更有实效。

易错点

  • 约束只写在架构文档里没有对应检查,实现随迭代漂移,等发现时已积累大量违规
  • 检查项过多且一律强制阻断,团队为过流水线写例外,约束形同虚设
  • 阈值拍脑袋定(如「延迟不超过 100ms」),没有基线数据支撑,检查频繁误报后被关闭
  • 检查失败没有负责人,红灯长期挂着,团队逐渐学会忽略流水线结果

数据来源与参考

  • 《Building Evolutionary Architectures》(Ford 等)
  • Neal Ford:Fitness Functions 演讲与文章
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌