跳转到内容

Big Ball of Mud 的经济学

一个 Big Ball of Mud 在经济上完全可能是理性的。

这听起来像是对整个系列的反驳。我们一直在讨论 Boundary 失效、Change Radius 扩大、Dependency 难以预测、Knowledge Concentration 和不断增加的 Regression Risk。既然如此,为什么不直接把系统“修好”?

因为 Architecture 并不会仅仅因为更整洁就自动创造 Business Value。

架构的经济价值来自它如何影响未来 Change:一次修改需要多少 Effort、多久可以完成、风险有多大、可以多准确地预测,以及 Organisation 在外部变化逼近时还有多少反应空间。

因此,一个结构严重侵蚀的系统,仍然可能是合理投资组合的一部分。如果它未来几乎不再需要变化、Replacement 已确定、剩余寿命很短,那么大规模 Reconstruction 也许永远无法回本。

反过来,同样的技术状态出现在一个持续增长的战略核心产品里,经济意义可能完全不同。

两个产品,技术质量相似,经济学完全不同

Section titled “两个产品,技术质量相似,经济学完全不同”

假设有两个在技术上都高度 Erode 的产品。

Product A 已接近生命周期末期。未来五年只有少量 Security Patch 和极少业务变化,Organisation 已经计划替代它。

Product B 是战略核心产品。每个月都有新 Feature、Integration、Regulation、Customer Variant 和市场压力。

两者的 Code Quality 可能同样糟糕,Dependency Graph 同样复杂,Change Radius 同样难预测。

但同一份 Architecture Debt 在 Product B 上会被反复“使用”。每一次新需求都要再次支付理解、协调、Regression 和 Risk Cost。

Product A 的 Debt 可能大部分只是静态存在。

两个技术上同样 Erode 的产品,因为未来 Change Demand 不同,经济合理性完全不同。

所以真正的问题不是:

系统有多脏?

而是:

未来还需要这个系统改变多少,而且这些变化有多重要?

Modularity、Boundary、Testability、Independent Deployment、Clear Ownership 等架构特性,主要在 Change 时产生价值。

一个从不再修改的系统,很少从更高 Changeability 中获得直接回报。

因此,Architecture Investment 很像对 Future Change Demand 的投资。

预计变化越频繁、越战略、越不可避免,降低 Change Cost 和 Uncertainty 的价值就越高。

这也解释了为什么同一 Organisation 对两个 Legacy System 可以做完全不同的决定:一个选择继续维护,另一个进行 Strangler Reconstruction。

两种决策都可能是专业的。

关键不是统一 Architecture Doctrine,而是每个系统未来承担的 Change Portfolio。

Technical Debt 的经济意义取决于它未来会被“触发”多少次。

Output Decline:不是工作变少,而是业务 Output 变少

Section titled “Output Decline:不是工作变少,而是业务 Output 变少”

Big Ball of Mud 中最容易被误解的一种现象是:Team 明明同样忙,甚至更忙,业务 Output 却下降。

原因可能并不是“Developer Productivity 变差”。

越来越多 Engineering Capacity 被用于让修改本身成为可能:Repository Exploration、Dependency Analysis、Regression、Coordination、Workaround、Rework、Release Safeguard、Expert Consultation、Environment Debugging。

这些活动都是真实工作。

只是它们没有直接增加新的业务能力。

因此,Engineer-Hours 可以保持稳定,而 Feature Throughput 下降。

Besker、Martini 和 Bosch 关于 Technical Debt 的研究也关注 Developer 因 Debt 而损失的生产时间。重要的是不要把这机械转化成一个固定百分比;不同系统、不同 Debt 类型和不同 Change Profile 差异巨大。

这里需要的是机制理解:

当越来越多 Capacity 用于理解和补偿系统,Organisation 得到的新业务 Output 就会下降,即使 Team 没有少工作。

Architecture Erosion 很难与单一 Business KPI 建立简单因果关系。

真实软件系统同时受到 Requirement Complexity、Team Experience、Tooling、Process、Market Condition、Organizational Structure、Technology Change 等大量因素影响。

因此,本文不会声称:

Big Ball of Mud 会把开发成本提高 47%。

这种精确数字没有足够普遍的经验基础。

更稳妥的方式,是讨论可观察的经济传导路径和 Proxy:Change Effort、Lead Time、Estimate Variance、Regression Work、Coordination、Onboarding、Turnover-induced Knowledge Loss、Cost of Delay 和 Tail Risk。

不能精确量化,不等于经济机制不存在。

相反,很多 Architecture Cost 的困难恰恰在于它们跨多个预算、Team 和时间段出现。

如果一个小 Feature 的 Change Radius 无法预测,Estimate 区间会扩大。

如果 Regression Radius 很大,Team 会增加 Test 和 Buffer。

如果只有少数 Expert 能确认影响,Lead Time 就取决于他们的 Availability。

如果多个 Team 必须一起修改,Planning 会增加 Coordination Dependency。

于是技术上的不确定性逐步变成计划不确定性,再变成 Business Risk。

未知 Change Radius 会逐步传导为 Estimate Uncertainty、Release Uncertainty 与 Business Risk。

这条路径很重要,因为 Stakeholder 通常并不会直接购买“更好的 Coupling”。

他们关心的是:什么时候能上线、承诺能否兑现、Regulation 能否按期完成、Opportunity 是否会错过。

Architecture 通过这些中间变量进入 Business。

Coordination Cost:Effort 不等于 Lead Time

Section titled “Coordination Cost:Effort 不等于 Lead Time”

一个 Feature 可能只有 20 Person-Hours 的实际 Implementation Effort,却需要三周才能上线。

不是因为 Developer 写得慢,而是因为工作包含等待:先等 Team B 的 API Change,再等 Shared Environment,再等 Key Expert Review,再等统一 Release Window。

在 Dependency-heavy System 中,Coordination Cost 往往以 Queue 的形式出现。

Business 体验的是三周 Lead Time,而不是 20 小时 Effort。

Cataldo、Herbsleb 和 Carley 的 Socio-Technical Congruence 工作提供了一个重要视角:技术 Dependency 与工作 Coordination Structure 是否匹配,会影响协作效率。

因此,Architecture Cost 不只存在于“做了多少工作”,也存在于“工作什么时候能够继续”。

Effort 是成本的一部分,等待和同步同样是成本。

一个稳定但偏高的成本仍然可以计划。

如果 Team 知道某类 Feature 永远需要十天,Organisation 可以在此基础上做 Portfolio Decision。

更危险的是 Variance。

两个看起来相似的 Ticket,一个三天完成,一个三周才发现 Hidden Dependency。一个 Upgrade 顺利,另一个突然触发五年前的 Integration Assumption。

这种 Heavy-Tail 式的不确定性会让 Estimate 更保守,Planning 增加 Buffer,Roadmap 对具体日期的信任下降。

Software Estimation 本来就困难。Jørgensen 等人的研究长期显示 Expert Estimation 存在广泛 Uncertainty。

Big Ball of Mud 不会创造全部 Estimation Problem,但它会增加一个额外来源:Team 甚至不知道自己还没有看到哪些结构影响。

因此,经济问题不只是平均成本上升。

不可预测性本身具有价格。

Stakeholder 为技术不可预测性买单

Section titled “Stakeholder 为技术不可预测性买单”

Stakeholder 不需要理解 Dependency Graph,仍然会支付这些成本。

它们会以不同形式进入 Business:更大的 Deadline Buffer、更保守的 Scope、更高 Contingency Budget、更多 QA、更多 Release Coordination、更晚的 Commitment,以及更慢的市场响应。

有时还会形成组织行为:Product Manager 不再提出某些 Feature,因为“那里太危险”;Sales 不敢承诺某些 Integration;Management 更倾向做外围功能,而不是修改核心流程。

这时 Architecture 已经影响 Product Strategy。

不是因为 Stakeholder 突然开始关心 Clean Code。

而是因为结构不确定性改变了可以安全承诺的事情。

最容易测的是实际发生的成本。

更难看见的是 Opportunity Cost。

如果 Team 花六周处理 Regression、Workaround 和 Coordination,这六周没有只“多花钱”。Organisation 同时失去了六周可以用于新 Feature、Security Improvement、Experiment、Customer Request 或 Platform Upgrade 的 Capacity。

更隐蔽的是,某些 Initiative 可能根本不会开始。

如果大家知道“核心 Billing 区域一改就很危险”,Roadmap 会自然偏向结构安全的小功能。

于是 Codebase 开始决定 Product Portfolio。

最昂贵的 Feature 有时不是实现得很贵,而是因为系统太危险而从未被实现。

Opportunity Cost 很难直接记到 Architecture Budget 上,却是真实经济影响。

Time-to-Market 并非对所有 Product 同样重要。

但在有市场窗口、Contract Deadline、Regulation 或 Competitive Response 的情况下,Delay 具有明确价值损失。

Cost of Delay 提醒我们:同一个 Feature 晚三个月上线,与按时上线,不只是 Development Cost 不同。

Cohen、Eliashberg 和 Ho 早期关于 New Product Development 的工作讨论 Performance 与 Time-to-Market 的 Trade-off。对于软件,Architecture 影响的正是 Organisation 把技术 Change 转化成市场响应的速度。

如果两个月被用于理解 Hidden Dependency,那么 Architecture Debt 并没有只消耗 Developer Time。

它消耗了 Opportunity Window。

Architecture 的经济价值不只在已知 Change 上。

它还可以被理解为一种 Option Value。

Sullivan、Griswold、Cai 和 Hallen 关于 Modularity Value 的工作使用过与 Option Thinking 相近的视角:模块化可以保留未来在局部进行替换、演化或投资的选择。

当 Boundary 清楚、Contract 稳定、Test 可靠时,Organisation 可以更晚决定:是否替换一个 Module、是否拆 Service、是否增加另一个 Client、是否改变 Workflow。

它不需要今天就执行这些改变。

真正有价值的是未来仍然拥有选择。

Big Ball of Mud 会缩小 Option Space,因为每一个大变化都先要求支付巨大 Understanding 和 Risk Cost。

Architecture 不只是让已知变化便宜,它还决定未来还有多少选择仍然现实可行。

但是:“我们不再需要 Feature”还不够

Section titled “但是:“我们不再需要 Feature”还不够”

反对 Modernization 时,一个常见论点是:

Product 已经稳定,我们不会再加很多 Feature。

这个论点可以完全合理。

但它只覆盖一类 Change。

长期 Software 还会面对很多不由 Product Roadmap 决定的变化。

Endogenous Change 来自系统和 Organisation 内部:Bug、Performance、Data Growth、新 User Flow、Technical Upgrade、Team Change、Operational Improvement。

这些 Change 有些可以延后,有些不能。

即使 Product Functionality 基本稳定,也可能仍需要修改 Platform、Dependency 或 Data Model。

Exogenous Change 来自外部环境:Browser、OS、Cloud Provider、Security Vulnerability、Partner API、Identity Provider、Law、Accessibility Standard、Data Protection、Regulation。

这些 Change 的时间点往往不是 Organisation 自己选择的。

计划内 Product Change 与外部强制 Change 最终都会作用在同一个 Software System 上。

所以,“没有 Feature Backlog”不等于 Future Change Demand 为零。

Software Evolution:环境会继续变化

Section titled “Software Evolution:环境会继续变化”

Lehman 的 Software Evolution 工作很早就强调,长期使用的软件会持续与其环境互动,并需要适应变化。

Framework 进入 EOL,Database Version 停止支持,Browser Security Policy 改变,Infrastructure Migration 发生,Partner System 更新 Contract。

Organisation 可以冻结自己的 Roadmap,却冻结不了系统外部世界。

Feature Backlog 冻结,不会冻结软件运行的环境。

Architecture Debt 会决定这些被迫变化究竟是局部 Upgrade,还是一次高风险 System Migration。

Security:Deadline 由别人决定的 Change

Section titled “Security:Deadline 由别人决定的 Change”

Security 是 Exogenous Change 最直观的例子之一。

Critical Vulnerability 出现时,Organisation 不能自由选择“以后再说”。

如果一个核心 Library 必须升级,而系统与旧 Version 深度耦合,Team 可能在攻击窗口内被迫完成过去多年一直回避的 Migration。

这时,Architecture Flexibility 直接变成 Risk Management。

一个容易升级的系统并不会消灭 Vulnerability。

但它能缩小从“发现问题”到“安全修复”的时间和不确定性。

因此,Changeability 不只是 Product Feature 的效率属性。

它还是 Security Response Capability。

Regulation 同样可能产生不可延期 Change。

Data Retention、Auditability、Accessibility、Privacy、Reporting Requirement 或 Industry Regulation 都可能要求系统在外部 Deadline 前改变。

对受监管产品来说,这种 Change 往往没有“Business 不想做就不做”的选项。

如果 Change Radius 很大、Data Ownership 不清、History Rule 只存在于 Expert Memory,Regulatory Response 会变得更贵,也更难证明正确。

这说明一个重要点:

Architecture Debt 不是只在创新时收费。它也会在 Compliance 时收费。

Architecture Economics 至少可以拆成三个不同维度。

一次实际 Change 需要多少 Effort?

包括 Implementation、Analysis、Test、Regression、Coordination、Rework、Release Safeguard。

Organisation 能否在合理区间内预测 Cost 和 Lead Time?

完全精确不现实,但如果两个相似 Ticket 的结果从三天到三个月随机波动,Portfolio Planning 会非常困难。

当外部 Change 突然发生时,Organisation 能多快、安全地响应?

Security、Regulation 和 Partner API Failure 往往测试的正是这一能力。

Big Ball of Mud 可以同时削弱三者:平均成本变高,Variance 变大,Response Window 变长。

一个业务 Change 周围被额外 Understanding、Regression、Coordination 与 System Work 包围。

Architecture 也会影响 Team Scaling。

如果一个系统只有极少数人能安全修改,招聘更多优秀 Developer 并不会立刻增加等比例 Throughput。

问题不是候选人质量。

而是新人的知识缺口主要不是语言、Framework 或通用工程能力,而是系统自己的历史 Context。

这种 Context 无法从招聘市场直接购买。

Organisation 需要用现有 Expert 的时间慢慢转移。

所以 Hiring Cost 不只是 Recruiter Fee 和 Salary。

还包括 Existing Team 为新人提供的 Training Capacity,以及新人成为真正独立 Contributor 之前的时间。

在结构清晰系统里,新 Developer 需要学习 Domain、Architecture Rule、Tooling 和主要 Flow。

在 Big Ball of Mud 中,他还要学习另一套东西:哪些 Boundary 实际不起作用,哪个 Service 不能碰,哪些 Event 有 Hidden Consumer,哪个 Test 不能信,谁知道某个历史 Decision,哪些 Formal Ownership 与实际责任不同。

Britto 等人关于全球分布式 Legacy Project Onboarding 的 Multi-Case Study 展示了 Onboarding 复杂性和 Context Dependency。

这类成本很难通过普通 Documentation 完全消除,因为真正的问题可能是系统结构本身缺少可预测性。

如果新 Developer 必须先学习组织所有的“例外地图”,Onboarding 就是在偿还一部分 Architecture Debt。

Turnover 在任何 Organisation 都有成本。

在依赖隐式 Knowledge 的系统里,这个成本更高。

Robillard 对 Turnover-Induced Knowledge Loss 的研究说明,离职可能带走难以替代的 Context。

Key Person 离开后,Organisation 不只是少一个 Developer。

它可能失去对 Historical Decision、Sonderfall、Risk Area 和 Hidden Contract 的解释。

替代者必须通过 Repository Exploration、Incident 和 Production Change 重新学习这些关系。

因此,Architecture Debt 与 Turnover 可以相互强化:结构越难懂,Knowledge 越集中;Knowledge 越集中,Turnover Risk 的经济后果越大。

Modernization 很难卖,还有一个根本原因:成本和收益不对称。

Reconstruction Cost 通常是立即、具体、可见的。

Management 可以看到:需要多少 Team、几个月、Migration Risk、Opportunity Cost。

收益则往往分散在未来:下一个 Feature 快一点、少一些 Regression、Estimate 稳一点、Onboarding 容易一点、Security Upgrade 更可控。

这些 Benefit 跨多个 Budget Period,甚至跨多个 Team。

因此 Status Quo 在 Budget Discussion 中拥有天然优势。

一个好的 Business Case 不能只说:

Code 会更干净。

它必须连接具体 Change Demand 和 Risk:哪些未来 Initiative 会被加速?哪些 Mandatory Change 会更安全?哪些 Lead Time 与 Coordination Dependency 会下降?

Architecture Investment 必须被翻译成 Business Option 和 Risk Reduction。

Tail Risk:很少发生,但发生时很贵

Section titled “Tail Risk:很少发生,但发生时很贵”

平均成本并不是全部。

一些最危险 Architecture Cost 属于 Tail Risk。

Critical Security Upgrade、Major Regulation、Cloud Migration、Key Expert Departure、Emergency Data Fix,也许几年才发生一次。

但一旦发生,Organisation 必须在很短时间内完成非常大的 Change。

一个结构高度侵蚀的系统,在平常可能“够用”,直到某个 Rare Event 要求它突然展示高 Changeability。

因此经济分析不能只看平均 Sprint Throughput。

还要问:

当少见但无法回避的大变化发生时,我们的损失分布尾部有多危险?

这也是 Architecture Flexibility 作为保险价值的一部分。

以上仍然不意味着每个 Big Ball of Mud 都应该被修复。

如果 Expected Change Demand 低,Replacement 已经计划,剩余寿命有限,Onboarding 和 Knowledge Risk 可控,Mandatory Change 仍能安全完成,那么继续运行完全可能是最佳经济决策。

Technical Debt 本来就不意味着“必须偿还”。

Debt 是关于 Future Cost 的选择。

如果 Future 根本不会触发太多 Cost,大规模偿还本身反而可能浪费资本。

因此,专业 Architecture Decision 需要抵抗两种 Religion:

  • “Legacy 一定要 Modernize”;
  • “既然还能跑,就永远不用处理结构”。

两者都忽略具体 Business Horizon。

Big Ball of Mud 可以在经济上长期工作。

如果产品稳定、变化很少、剩余寿命有限,那么接受 Technical Erosion 完全可能合理。全面 Reconstruction 自己也有 Cost、Risk 和 Opportunity Cost,不是每一笔 Debt 都值得偿还。

但随着 Change Demand 增长,计算会变化。

越来越多 Development Capacity 可能流向不创造新业务价值、却让既有系统能够继续变化的工作:Understanding、Regression、Coordination、Workaround、Rework、Safeguard。

Technical Dependency 会制造 Lead Time,未知 Change Radius 会进一步扩大 Estimate Uncertainty,高 Change Cost 甚至会在写第一行 Code 之前就改变 Product Decision。

同时还有单次 Change 之外的成本:Onboarding 需要资深同事投入,Key Person 离开会造成 Knowledge Loss,被结构性额外工作占用的 Capacity 无法用于 Feature、Improvement 和 Risk Reduction。

但从这些事实仍不能推导出一般性的 Modernization Duty。

继续运行一个 Big Ball of Mud,本质上是一场关于未来的经济下注。它在 Expected Change Demand 很低、剩余寿命有限、Knowledge Risk 可控、Mandatory Change 仍能处理时更合理。

问题在于,一部分真实 Change Demand 并不受 Roadmap 控制。Security、Regulation、Platform Change、External API 都可能要求系统回应,即使 Organisation 不再计划任何新 Feature。

Architecture 的经济价值不只是降低 Change 的平均成本,更在于把成本、Duration 和 Risk 保持在可管理区间。

冻结 Feature Backlog,并不会冻结软件所处的环境。

Organisation 为 Big Ball of Mud 支付的不只有 Development Time。

最坏情况下,它支付的是:当变化已经不能再推迟时,自己是否仍有能力及时响应。

  • Besker, T., Martini, A. & Bosch, J. (2019). Software Developer Productivity Loss Due to Technical Debt – A replication and extension study examining developers’ development work. Journal of Systems and Software, 156, 41–61. DOI: 10.1016/j.jss.2019.06.004.
  • Britto, R., Cruzes, D. S., Šmite, D. & Sablis, A. (2018). Onboarding software developers and teams in three globally distributed legacy projects: A multi-case study. Journal of Software: Evolution and Process, 30(4), e1921. DOI: 10.1002/smr.1921.
  • Carrière, S. J., Kazman, R. & Ozkaya, I. (2010). A cost-benefit framework for making architectural decisions in a business context. Proceedings of the 32nd ACM/IEEE International Conference on Software Engineering, Volume 2, 149–157. DOI: 10.1145/1810295.1810317.
  • Cataldo, M., Herbsleb, J. D. & Carley, K. M. (2008). Socio-technical congruence: A framework for assessing the impact of technical and work dependencies on software development productivity. Proceedings of the Second ACM-IEEE International Symposium on Empirical Software Engineering and Measurement, 2–11. DOI: 10.1145/1414004.1414008.
  • Cohen, M. A., Eliashberg, J. & Ho, T.-H. (1996). New Product Development: The Performance and Time-to-Market Tradeoff. Management Science, 42(2), 173–186. DOI: 10.1287/mnsc.42.2.173.
  • Jørgensen, M. (2004). A review of studies on expert estimation of software development effort. Journal of Systems and Software, 70(1–2), 37–60. DOI: 10.1016/S0164-1212(02)00156-5.
  • Jørgensen, M. (2007). Forecasting of software development work effort: Evidence on expert judgement and formal models. International Journal of Forecasting, 23(3), 449–462. DOI: 10.1016/j.ijforecast.2007.05.008.
  • Jørgensen, M. & Shepperd, M. J. (2007). A Systematic Review of Software Development Cost Estimation Studies. IEEE Transactions on Software Engineering, 33(1), 33–53. DOI: 10.1109/TSE.2007.3.
  • Lehman, M. M. (1980). Programs, life cycles, and laws of software evolution. Proceedings of the IEEE, 68(9), 1060–1076. DOI: 10.1109/PROC.1980.11805.
  • Lehman, M. M. (1996). Laws of Software Evolution Revisited. In: Montangero, C. (Hrsg.), Software Process Technology, Lecture Notes in Computer Science, Vol. 1149, 108–124. Springer. DOI: 10.1007/BFb0017737.
  • Robillard, M. P. (2021). Turnover-Induced Knowledge Loss in Practice. Proceedings of the 29th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering, 1292–1302. DOI: 10.1145/3468264.3473923.
  • Sullivan, K. J., Griswold, W. G., Cai, Y. & Hallen, B. (2001). The Structure and Value of Modularity in Software Design. Proceedings of the 8th European Software Engineering Conference held jointly with the 9th ACM SIGSOFT International Symposium on Foundations of Software Engineering, 99–108. DOI: 10.1145/503209.503224.
  • Zhang, Z., Zhang, H., Qian, Z. & Lau, B. (2021). An Investigation of the Android Kernel Patch Ecosystem. 30th USENIX Security Symposium (USENIX Security 21), 3649–3666. USENIX Association.