2004年,一位名为Michael Feathers的软件工程师在《Working Effectively with Legacy Code》一书中写下了一个令人不安的定义:“遗留代码就是没有测试的代码。“这个定义的潜台词是:如果你不敢改,它就是遗留代码。

二十多年后的今天,这个定义需要更新。遗留代码不只是没有测试的代码——它是任何让开发者感到恐惧的代码。恐惧犯错、恐惧引入bug、恐惧被责备、恐惧浪费时间。这种恐惧并非技术问题,而是深植于人类认知系统和组织行为中的系统性障碍。

2024年Standish Group的CHAOS报告显示,83.9%的IT项目未能完全达成目标,其中31.1%彻底失败。而在这些失败项目中,与技术债务和代码质量相关的因素占比超过40%。更令人警醒的是,俄勒冈州立大学2020年发表在ICSE的一项研究揭示:认知偏见会显著影响开发者的决策,将他们推向错误的行为路径。

当重构失败时,问题往往不在重构本身。

技术债务的复利陷阱

Ward Cunningham在1992年创造了"技术债务"这个隐喻,本意是描述一种有意识的权衡——为了快速交付而暂时牺牲代码质量,并在日后偿还。然而三十多年后,这个隐喻被严重滥用。

Martin Fowler在2009年提出的"技术债务象限"揭示了问题的本质。他按照两个维度划分债务:谨慎vs轻率有意vs无意。真正的技术债务——谨慎且有意的——是合理的工程决策。问题在于,大量所谓的"技术债务"实际上属于轻率且无意的类别:开发者根本没有意识到自己在制造问题。

quadrantChart
    title 技术债务象限
    x-axis 轻率 --> 谨慎
    y-axis 无意 --> 有意
    quadrant-1 真正的技术债务
    quadrant-2 设计疏漏
    quadrant-3 混乱的代码
    quadrant-4 欠考虑的捷径
    谨慎有意: [0.85, 0.85]
    谨慎无意: [0.85, 0.25]
    轻率有意: [0.25, 0.85]
    轻率无意: [0.25, 0.25]

技术债务的危险在于它的复利效应。François Wouts在其技术债务利率研究中指出:某些技术债务具有高利率——每推迟一个月偿还,利息成本就会翻倍。这不是比喻。当一个模块的设计缺陷导致每次新功能开发都需要额外3天适配,而新功能每月增加2个,一年后的维护成本将是最初的8倍。

2022年CodeScene对39个商业代码库的定量研究(发表于ACM)提供了更具体的数据:低质量代码的缺陷数量是高质量代码的15倍,开发速度降低50%,问题修复时间增加124%。研究负责人Adam Tornhill总结:“组织浪费了23-42%的开发者时间来应对技术债务。”

为什么明知代价如此高昂,重构仍然屡屡失败?

沉没成本谬误:为什么我们不愿放弃烂代码

2011年,行为经济学家Daniel Kahneman(诺贝尔经济学奖得主)在《Thinking, Fast and Slow》中系统阐述了一个核心观点:人类决策受到损失厌恶(Loss Aversion)的深刻影响——失去100元的痛苦,大约是获得100元快乐的2倍。

这个心理学原理在软件工程中有着惊人的解释力。当开发者面对一段已经投入大量时间的代码时,即使明知道重构会带来更好的结果,他们仍然倾向于继续维护旧代码。这就是沉没成本谬误(Sunk Cost Fallacy)——已经投入的成本不应该影响未来决策,但它们实际上会。

Medium上的一篇文章《Why Developers Rewrite Instead of Fix》揭示了一个悖论:开发者既害怕重写(因为沉没成本),又害怕修改遗留代码(因为不确定性)。这种双重恐惧导致了一种瘫痪状态——既不重构,也不重写,只是不断堆叠新代码。

更深层的问题在于IKEA效应。2012年,Norton、Mochon和Ariely发表的心理学研究(刊于《Journal of Consumer Psychology》)发现:人们对自己亲手组装的物品会赋予过高的价值。这个效应在软件领域同样适用——开发者倾向于高估自己编写的代码质量,即使客观评估显示代码存在严重问题。

2024年一篇系统综述(Wiley《Journal of Marketing》)对IKEA效应进行了元分析,确认了这个偏见的普遍性和顽固性。当一位开发者说"这段代码我能理解,没问题"时,他可能正在经历IKEA效应——熟悉感被误认为质量

确认偏见与自我服务偏见:我们如何欺骗自己

确认偏见(Confirmation Bias)是认知心理学中最广泛研究的偏见之一。在软件工程中,它表现为:开发者倾向于寻找支持自己假设的证据,而忽略反驳性证据。

2013年,Open University的研究发表在《Software Quality Journal》上,发现确认偏见指标可以预测代码缺陷——效果甚至不输于传统的缺陷预测模型。当开发者相信某段代码"应该没问题"时,他们编写的测试往往只覆盖正常路径,而忽略边界情况。

自我服务偏见(Self-serving Bias)则更加隐蔽。2006年发表在《Industrial Management & Data Systems》上的研究发现:IT支持人员在归因时,倾向于将成功归因于自己,将失败归因于外部因素。这种归因模式在团队层面会产生什么后果?

当一个重构项目失败时:

  • 发起者归因于"团队配合不力"或"业务需求变更”
  • 执行者归因于"目标不清晰"或"时间不够”
  • 管理者归因于"技术能力不足"

没有人承认:我低估了复杂度我没有做足调研我被偏见蒙蔽了判断

这种归因模式形成了一个认知闭环:既然问题都是外部的,那么下一次只需要"更努力"或"更幸运"。偏见本身从未被审视。

规划谬误:为什么重构总是超时

规划谬误(Planning Fallacy)由Kahneman和Tversky在1979年首次提出:人们倾向于低估任务完成时间,即使他们拥有类似任务的过往经验。

2013年发表在AIS上的研究探讨了规划谬误在软件项目中的表现。研究发现,软件项目的预估时间平均比实际时间低40-60%。这种系统性低估在重构项目中更为严重——因为重构的"收益"难以量化,而"成本"(时间投入)却被高度关注。

一个典型的场景:

管理者问:“重构这个模块需要多久?” 开发者想:“我大概了解这个模块,应该一周搞定。” 现实是:模块有未知的依赖、边缘情况、历史遗留问题。 最终结果:三周后项目还在进行,管理者失去耐心,项目被叫停。

这里存在两个层面的认知问题:

第一层:内部视角vs外部视角。 开发者只关注"这个特定模块",而忽略了"类似模块的统计规律"。Nobel奖得主Kahneman建议使用"外部视角"——参考类似项目的实际耗时数据——可以显著改善估算准确性。

第二层:乐观偏见。 2025年发表在《LinkedIn》上的研究指出,规划谬误与乐观偏见高度相关——人们倾向于想象"最好情况"而非"平均情况"。当开发者在脑海中预演重构过程时,他们想象的是"一切顺利"的场景,而非"意外频发"的现实。

心理安全感:Google发现的隐形因素

2015年,Google发布了Project Aristotle的研究结果,这是该公司对团队绩效进行的最全面研究。研究团队分析了180个团队、超过250个变量,试图找出高效团队的决定性因素。

结果出人意料:技术能力、个人智商、经验年限——这些"硬指标"都不是最关键的。心理安全感(Psychological Safety)——团队成员相信自己在提出问题、承认错误、寻求帮助时不会受到惩罚——才是核心预测因子。

哈佛商学院教授Amy Edmondson最早系统研究了这个概念,将其定义为:“团队共享的信念,相信团队不会因提出问题、承认错误或提出新想法而惩罚或羞辱成员。”

心理安全感与重构失败有什么关系?

没有心理安全感的团队中:

  • 开发者不敢承认"我不理解这段代码"
  • 开发者不敢提出"这个重构计划有问题"
  • 开发者不敢报告"我引入了一个bug"
  • 开发者不敢建议"我们需要更多时间"

有心理安全感的团队中:

  • 早期发现问题,避免后期灾难
  • 集体智慧被充分利用
  • 错误被视为学习机会而非惩罚理由

2025年发表在《ScienceDirect》上的系统综述进一步确认:心理安全感是敏捷软件开发团队成功的关键前因变量。研究指出,心理安全感的建立需要个人、团队和领导层三个层面的共同投入。

康威定律与组织债务

1968年,程序员Melvin Conway发表了一篇论文,其中包含一个被后世无数次引用的观点:“设计系统的组织受限于产生设计的组织的沟通结构。"——这就是著名的康威定律(Conway’s Law)。

Martin Fowler在2022年的博客中进一步阐释:软件架构往往会镜像开发团队的组织结构。如果团队被分割为前端组、后端组、数据库组,那么代码结构也会呈现三层分离——无论这是否是最佳架构。

康威定律对重构失败的启示是:组织不改变,架构很难改变。

当一个组织试图重构代码时,如果团队边界、沟通模式、决策流程保持不变,新代码很快就会"回归"到旧模式。这不是技术问题,而是组织引力——系统会自然演化出与组织结构匹配的架构。

更深层的问题在于组织债务(Organizational Debt)。2015年,Steve Blank在Forbes上撰文指出:组织债务是"为了’先把事做完’而在早期阶段做出的所有人员/文化妥协”。与技术债务类似,组织债务也会积累——糟糕的招聘决策、被容忍的毒性文化、被忽视的培训需求。

2024年发表在《PMC》上的研究正式定义了组织债务的概念,将其描述为"过时的结构、政策和流程的积累,这些阻碍了组织的进步和适应性"。研究发现,组织债务与技术债务高度相关——混乱的组织往往产生混乱的代码。

第二系统效应:重构的陷阱

Fred Brooks在1975年的《人月神话》中提出了"第二系统效应"(Second System Effect):设计师在第一次成功后,往往会为第二个系统添加过多的功能过度的复杂性

这个效应在重构项目中频繁出现:

  • 开发者决定"趁机"改进架构
  • 改进范围不断扩大
  • 新设计过于"完美主义"
  • 项目失控,最终失败

Wikipedia的条目指出:第二系统效应源于"第一次成功后增加的信心,以及从第一个系统中积累的、被推迟的想法"。当开发者终于获得重构的机会时,他们往往希望"一次性解决所有问题"——这正是第二系统效应的典型表现。

正确的做法是什么?Boy Scout Rule:每次修改代码时,让代码比你发现它时稍微好一点。这个原则看似微不足道,但2024年一篇Medium文章指出:如果持续应用Boy Scout Rule,一个代码库可以在189年内被完全重构——当然,这太慢了。关键在于:增量改进是可持续的,大规模重构往往是不可持续的。

如何破解困局

理解了认知偏见和组织障碍,才能设计有效的干预策略。

策略一:使用外部视角进行估算

不要问"这个重构需要多久",而要问"类似的重构项目实际花了多久"。Kahneman的研究表明,外部视角可以显著改善估算准确性。

策略二:Strangler Fig模式

Shopify在2020年详细介绍了Strangler Fig模式在遗留代码重构中的应用。其核心思想是:渐进式替换,而非一次性重写。

sequenceDiagram
    participant Client
    participant Facade
    participant Legacy
    participant New
    
    Client->>Facade: 请求
    Facade->>Legacy: 路由到旧系统
    Legacy-->>Facade: 响应
    Facade-->>Client: 返回
    
    Note over Facade,New: 渐进迁移
    
    Client->>Facade: 请求
    Facade->>New: 路由到新系统
    New-->>Facade: 响应
    Facade-->>Client: 返回

这个模式的关键优势在于:

  • 每一步都是可逆的
  • 每一步都可以独立验证
  • 业务连续性不受影响

策略三:建立心理安全感

Google在Project Aristotle之后发布了一套实践指南,包括:

  • 领导者示范脆弱性:承认自己的错误和不确定性
  • 好奇而非评判:用"发生了什么"代替"为什么会这样"
  • 正常化失败:将失败视为学习机会

策略四:对抗确认偏见

在测试和代码评审中引入"魔鬼代言人"角色:

  • 指定一人专门寻找反例
  • 使用mutation testing强制测试边界情况
  • 代码评审时,明确要求评审者提出"这个设计可能失败的三种方式"

策略五:量化技术债务利息

使用SQALE方法或CodeScene等工具,将技术债务转化为可量化的指标。François Wouts建议:计算每个模块的"利息率"——维护这个模块每月消耗多少额外时间。当这个数字被明确呈现时,决策者更容易理解重构的ROI。

技术之外

代码重构失败,表面上是技术问题,本质上是人和组织的问题

认知偏见——沉没成本谬误、损失厌恶、IKEA效应、确认偏见、规划谬误——共同构成了一个认知陷阱,让开发者在潜意识中抗拒改变。组织因素——心理安全感缺失、康威定律、组织债务——则构成了一个结构性障碍,让有意义的改变难以发生。

理解这些因素,不是为了"克服"它们(偏见是人类认知的固有特性),而是为了设计与之共存的工作方式

1957年,认知科学家Herbert Simon提出了"有限理性"(Bounded Rationality)的概念:人类决策受到信息、认知能力和时间的限制,我们永远无法做出"最优"决策,只能在约束下寻求"满意解"。

重构的失败,某种程度上是对有限理性的无视——我们假设开发者能够完美评估风险、做出理性决策、执行完美计划。现实是,开发者是人,团队是人组成的,组织是人构建的。

承认人的局限,才能设计出让重构真正成功的流程。不是更大的重写计划,而是更小的迭代;不是更严格的要求,而是更安全的实验空间;不是更完美的设计,而是更容错的演进。

重构不是技术项目,是组织变革项目。当技术决策者开始理解这一点,失败率才可能真正下降。


参考资料

  1. Standish Group. (2024). CHAOS Report 2024.
  2. Chattopadhyay, S., et al. (2020). A Tale from the Trenches: Cognitive Biases and Software Development. ICSE 2020.
  3. Fowler, M. (2009). Technical Debt Quadrant. martinfowler.com.
  4. Tornhill, A., & Borg, M. (2022). Code Red: The Business Impact of Code Quality. ACM Digital Library.
  5. Cunningham, W. (1992). The WyCash Portfolio Management System. OOPSLA 1992.
  6. Norton, M. I., Mochon, D., & Ariely, D. (2012). The IKEA Effect: When Labor Leads to Love. Journal of Consumer Psychology.
  7. Edmondson, A. (1999). Psychological Safety and Learning Behavior in Work Teams. Administrative Science Quarterly.
  8. Google re:Work. (n.d.). Guide: Understand Team Effectiveness.
  9. Conway, M. E. (1968). How Do Committees Invent? Datamation.
  10. Brooks, F. P. (1975). The Mythical Man-Month. Addison-Wesley.
  11. Kahneman, D., & Tversky, A. (1979). Intuitive Prediction: Biases and Corrective Procedures. TIMS Studies in Management Science.
  12. Lehman, M. M. (1974). Programs, Life Cycles, and Laws of Software Evolution. Proceedings of the IEEE.
  13. Feathers, M. (2004). Working Effectively with Legacy Code. Prentice Hall.
  14. Shopify Engineering. (2020). Refactoring Legacy Code with the Strangler Fig Pattern.
  15. Wouts, F. (n.d.). Evaluating Technical Debt’s Interest Rate. fwouts.com.