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)的概念:人类决策受到信息、认知能力和时间的限制,我们永远无法做出"最优"决策,只能在约束下寻求"满意解"。
重构的失败,某种程度上是对有限理性的无视——我们假设开发者能够完美评估风险、做出理性决策、执行完美计划。现实是,开发者是人,团队是人组成的,组织是人构建的。
承认人的局限,才能设计出让重构真正成功的流程。不是更大的重写计划,而是更小的迭代;不是更严格的要求,而是更安全的实验空间;不是更完美的设计,而是更容错的演进。
重构不是技术项目,是组织变革项目。当技术决策者开始理解这一点,失败率才可能真正下降。
参考资料
- Standish Group. (2024). CHAOS Report 2024.
- Chattopadhyay, S., et al. (2020). A Tale from the Trenches: Cognitive Biases and Software Development. ICSE 2020.
- Fowler, M. (2009). Technical Debt Quadrant. martinfowler.com.
- Tornhill, A., & Borg, M. (2022). Code Red: The Business Impact of Code Quality. ACM Digital Library.
- Cunningham, W. (1992). The WyCash Portfolio Management System. OOPSLA 1992.
- Norton, M. I., Mochon, D., & Ariely, D. (2012). The IKEA Effect: When Labor Leads to Love. Journal of Consumer Psychology.
- Edmondson, A. (1999). Psychological Safety and Learning Behavior in Work Teams. Administrative Science Quarterly.
- Google re:Work. (n.d.). Guide: Understand Team Effectiveness.
- Conway, M. E. (1968). How Do Committees Invent? Datamation.
- Brooks, F. P. (1975). The Mythical Man-Month. Addison-Wesley.
- Kahneman, D., & Tversky, A. (1979). Intuitive Prediction: Biases and Corrective Procedures. TIMS Studies in Management Science.
- Lehman, M. M. (1974). Programs, Life Cycles, and Laws of Software Evolution. Proceedings of the IEEE.
- Feathers, M. (2004). Working Effectively with Legacy Code. Prentice Hall.
- Shopify Engineering. (2020). Refactoring Legacy Code with the Strangler Fig Pattern.
- Wouts, F. (n.d.). Evaluating Technical Debt’s Interest Rate. fwouts.com.