过早优化是万恶之源:50 年工程史反复在教我们的一件事

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil ." ------ Donald Knuth, Structured Programming with go to Statements, ACM Computing Surveys, 1974

这句话已经被引用了 50 年。

它依然有效,恰恰是因为它描述的那个陷阱,从来没有真正被解决过------开发者总是在不该优化的时候优化、不该抽象的时候抽象、不该重写的时候重写

这篇文章不打算讲故事,也不堆砌名词。我们用软件工程史上几个被反复验证、有据可查的论断和案例,来客观地说清楚一件事:

为什么"过度优化"是一种系统性的反模式,以及业界沉淀出的应对方法。


一、它在工程界有名字

很多人陷在"优化怪圈"里却不自知,部分原因是它没有一个统一的中文叫法。但在英文工程语境里,它的几种典型形态早已被命名、归类、写进经典著作。

1. Premature Optimization(过早优化)

来源:Knuth (1974)

需要澄清的是 Knuth 的原意------他不反对优化 ,他反对的是在测量之前的优化。他完整的论断是:97% 的代码不值得被优化,但有 3% 的关键路径必须被认真优化。判断该不该优化,要靠 profiling 数据,而不是直觉。

2. Speculative Generality(投机性通用化)

来源:Martin Fowler, Refactoring: Improving the Design of Existing Code (1999, 2nd ed. 2018,中文版《重构(第2版)》)。

这是 Fowler 在书中明确列出的"代码坏味"之一。典型表现:

  • 只有一个实现的 interface
  • 永远不会被传非默认值的"可配置参数"
  • "为了未来扩展"预留的钩子函数

Fowler 给的判断标准很直接:"If you need it, do it; if you don't, don't."

3. Gold Plating(镀金)

来源:早期出现在 IEEE 软件工程术语和 PMBOK(Project Management Body of Knowledge,《项目管理知识体系指南》中文版)中。

指的是在已满足需求后继续添加用户未要求的功能或细节。在项目管理领域,它被明确列为范围管理风险------因为它会消耗预算、延长周期,且不带来对应的客户价值。

4. Bikeshedding(自行车棚效应)

来源:C. Northcote Parkinson, Parkinson's Law: The Pursuit of Progress (1957,中文版《帕金森法则》)。

软件工程界的使用,源自 Poul-Henning Kamp 1999 年在 FreeBSD-Hackers 邮件列表的著名邮件 "A bike shed (any colour will do) on greener grass..."

它描述的是一种注意力错配------团队倾向于在小事上花掉远超核心议题的讨论时间。Code Review 中常见的形态:

  • 命名风格争论 30 分钟
  • 缩进/格式占据 80% 的评论
  • 真正的架构问题反而没人讨论

二、为什么过度优化是有害的

如果只用一句话概括,那就是:

它让你用工程上看起来正确的行为,回避了工程上真正困难的问题。

展开看,至少有四个客观成本。

1. 机会成本

每一小时投入到没有人要求的优化,都是从真正有价值的工作那里偷走的时间。

DeMarco 和 Lister 在 Peopleware (1987,中文版《人件(第3版)》) 中给出的核心观察是:知识工作者真正的产能差异,不在编码能力,而在注意力如何分配。同样的 8 小时,决定产出的是"你在做什么"而不是"你做得多努力"。

2. 边际效益递减

Pareto 原则(80/20 法则)在软件工程领域被反复印证。Knuth 那句"97%"也是它的同义表达------性能瓶颈通常集中在很小一部分代码里。对非热点路径做优化,投入和产出严重不成比例。

这个判断不是直觉,是过去半个世纪 profiling 工具反复验证过的事实。

3. 复杂度成本

John Ousterhout 在 A Philosophy of Software Design (2018,中文版《软件设计的哲学(第 2 版)》,人民邮电出版社 2024) 中提出一个核心论断:

复杂度(complexity)是软件系统最重要、也是最持久的成本。

每一次"为未来准备的抽象"、每一层"为优雅而引入的间接",都在增加:

  • 新人理解系统的时间
  • 修改时需要考虑的连带影响
  • bug 藏身的角落

Fred Brooks 在 The Mythical Man-Month (1975,中文版《人月神话(40 周年中文纪念版)》) 里也说过类似的话:conceptual integrity(概念一致性)是系统设计中最重要的考量。过度抽象的代价,常常是牺牲掉这种一致性。

4. 反馈延迟成本(最致命的一个)

这是最容易被忽略的一类成本。

Eric Ries 在 The Lean Startup (2011,中文版《精益创业》) 里把它表达为 Build-Measure-Learn 循环:未经市场验证的假设没有价值,在反馈到来之前所做的所有"完美准备",都可能因为方向本身错了而整体归零

一个被反复引用的反例,来自 Joel Spolsky 2000 年的文章 Things You Should Never Do, Part I。文章详细记录了 Netscape 的决策:因为认定老代码"不够好",团队决定从零重写浏览器。重写持续了将近 3 年,期间几乎没有产品演进。等到新版本发布时,市场已经被 IE 拿走了。

Spolsky 的结论是:

"It's harder to read code than to write it. (...) Throwing away the code means throwing away your knowledge."

那不是"代码不够优雅"的代价,而是整个公司命运的代价。


三、为什么我们如此容易陷进去

不是因为懒,恰恰相反,陷进去的往往是最在乎质量的那批人

业界对这个现象有几个互相印证的解释:

优化是少数完全可控的事。 业务会变、需求会变、老板想法会变。但代码不会。在不确定性扎堆的工作中,"把这段代码改得更漂亮"是少数几件结果完全由自己决定的事。

优化有即时反馈。 重构之后 IDE 立刻变绿、测试立刻通过、Lint 立刻消停。而业务价值要数周乃至数月才能验证。

优化是一种"完美主义防御"。 只要还在打磨,就不用面对评判。一旦交付,就要接受真实世界的反馈------而那个反馈可能是负面的。"还差一点点"是一种心理上的避风港。

优化容易和职业身份绑定。 "我是一个写优雅代码的工程师"成为一种自我认同,而非可被取舍的工程权衡。这一点比技术原因更难以察觉。


四、行业沉淀的应对原则

过去半个世纪的软件工程实践,沉淀出几条被广泛接受、有出处的判断框架。它们不是个人经验,而是经过大规模工程验证的原则。

1. YAGNI(You Aren't Gonna Need It)

来源:Ron Jeffries 在 XP(Extreme Programming)实践中提出,Kent Beck 在 Extreme Programming Explained (1999,中文版《解析极限编程》) 中将其确立为 XP 核心原则。

它的逻辑是:

  • 预测未来需求的准确率,远低于你以为的
  • 即使预测对了,未来真正实现时所知信息远多于现在,方案会更好
  • 提前实现的代码会成为未来变更的阻力

结论:只为已知的、明确的需求写代码。

2. Rule of Three(三次法则)

来源:Don Roberts 提出,被 Martin Fowler 收录在 Refactoring (1999) 中。

判断什么时候该抽象的规则非常简单:

  • 第一次出现 → 就这么写
  • 第二次出现 → 容忍重复
  • 第三次出现 → 此时你才真正知道"什么是共同的、什么是变化的"

Sandi Metz 在博客文章 The Wrong Abstraction (2016) 中进一步阐述了这条法则的反面:

"Prefer duplication over the wrong abstraction."

她的观点是:错误的抽象比重复的代码更难修复,因为它会绑定所有调用方

3. KISS(Keep It Simple, Stupid)

来源:洛克希德首席工程师 Kelly Johnson 在 1960 年代提出,后被软件工程界广泛采纳。

它和 Ousterhout 的"复杂度是核心成本"互为印证:简单方案的总成本,通常低于复杂方案------即使后者在某些维度看起来更先进。

4. Worse is Better(劣即是优)

来源:Richard P. Gabriel 在 Lisp: Good News, Bad News, How to Win Big (1991) 中提出,后续整理为独立论文 The Rise of "Worse is Better"

Gabriel 用这个概念解释一个看似反直觉的现象:简单、能用、能演进的设计,往往在长期竞争中击败完美但难落地的设计。

C 击败 Lisp 是他原始论文的例子。后来的从业者用它解释了从 JavaScript 到 React 到无数"不完美但获胜"的技术路径。

5. MVP(最小可行产品 / Minimum Viable Product)

来源:Eric Ries, The Lean Startup (2011),源头可追溯到 Steve Blank 的客户开发方法论。

核心承认是:没有人能在交付之前知道什么是"对的" 。最高效的路径不是把方案做完美再交付,而是用最小成本交付,用真实反馈指导后续投入


五、怎么判断自己正陷在里面

理论之后,回到实操。判断"是否陷入优化怪圈",可以用几个客观信号:

信号 1:你说不清"做完"长什么样

如果一个任务没有明确的 Definition of Done (Scrum 术语),那它一定会被无限延伸。Definition of Done 的价值,不在于定义结果,而在于定义边界。

动手前用一句话写下"做完了"是什么样,贴在显眼的位置。当你想"再加一个抽象"时------它在这句话里吗?不在,就停。

信号 2:你的优化没有 profiling 数据支撑

按 Knuth 的判断,任何未经测量的性能优化都属于过早。

问自己三个问题:

  1. 当前性能是不是业务/用户感知的瓶颈?
  2. Profiling 数据有没有定位到具体热点?
  3. 优化的预期收益是不是大于它引入的复杂度?

三个都答不上来,就先别动。

信号 3:抽象只有一个实现

这是 Fowler 的 Speculative Generality 最直接的检测方法。

打开 IDE,查一下这个 interface 有几个 implementation。如果只有一个,你大概率不需要它。 等到第三次重复出现时再抽象(Rule of Three),那时你才真正知道什么该抽出来。

信号 4:你在重构无关的代码

Boy Scout Rule(Robert C. Martin, Clean Code, 2008,中文版《代码整洁之道》)经常被错误使用------"离开营地时让它比来时更干净"被解读为"借机重构整个模块"。

它的本意是小幅、本地的清理 。判断边界是:清理能不能在当前任务的 commit 里独立提交,且不影响主任务的可审查性?

如果你的 PR 标题是"修一个 bug"但 diff 是 +800 / -600,那不是 Boy Scout,那是借机镀金


六、一个必须澄清的边界

反对过度优化,不等于鼓励技术债务的累积。这是常见的误读。

两者的区别在于决策依据:

维度 过度优化 合理工程 粗制滥造
关注点 想象中的未来需求 当前明确需求 + 已知风险 仅交付,不管后续
抽象时机 提前预设 出现重复后 完全无抽象
性能优化依据 直觉、洁癖 profiling 数据 不考虑
测试覆盖 追求 100% 覆盖关键路径与边界 缺失或形式化
决策方式 自我驱动 价值驱动 工期驱动

合理的工程实践,是在价值、成本、风险 三者之间持续寻找平衡点。过度优化和粗制滥造,是同一根坐标轴的两个极端,都背离了工程的本质。


七、AI 时代的新变量:当过度工程从陋习变成默认产出

文章到这里讨论的全部是「人类」的过度工程倾向。但 2023 年以来,这个老问题出现了一个全新的变量------AI 写的代码默认就是过度工程

Andrej Karpathy 在 X 上的一段公开观察被反复引用:

"它们真的很喜欢把代码和 API 搞复杂,堆砌抽象概念,不清理死代码......明明 100 行能搞定的事情,非要实现成 1000 行的臃肿架构。"

"模型会代你做错误假设,然后不假思索地执行。它们不管理自身的困惑,不寻求澄清,不呈现矛盾,不展示权衡,在应该提出异议时也不反驳。"

把这两段话对照本文前面讨论过的反模式,几乎是逐条对应:

  • 堆砌抽象概念 → Speculative Generality
  • 100 行的事情写成 1000 行 → YAGNI 反面
  • 不清理死代码、改动无关代码 → Boy Scout Rule 的错误使用
  • 不假思索地执行 → Premature Optimization
  • 不呈现权衡、不提出异议 → Bikeshedding 的反面(避难就易)

也就是说,本文列举的全部反模式,正在被 LLM 工业化、规模化地生产。这带来三个新的工程现实:

1. 过度工程从「慢性病」变成了「急性病」

人类工程师做过度设计,一周也许产出 200 行多余代码;LLM 一次会话就能产出 2000 行。代码库被淹没的速度被压缩到原来的 1/10。技术债的积累不再是按月计算,而是按 PR 计算。

2. 工程判断从「奢侈品」变成「必需品」

不熟悉 YAGNI、KISS、Rule of Three 的开发者,过去只是「写得慢一点」;今天意味着他们的代码库会以远超想象的速度堆积技术债。缺少工程纪律的人加上 AI,等于屎山生成器------AI 不会替你做价值判断,它只负责把你说的话最大化执行。

3. 工程纪律正在被「外置」给 LLM

应对方式正在被工程社区自发地探索------核心思路可以概括为:在 LLM 写代码之前,先把人类积累的工程纪律以可执行的规则形式喂给它,让模型在生成时受到这些规则的筛检。这类规则集常见的几条,翻译成本文的语言其实是:

注入的规则 对应本文原则
简洁优先 KISS + YAGNI + Worse is Better
精准修改 Boy Scout Rule 正确用法 + 避免镀金
编码前思考 Definition of Done + 测量优先
目标驱动执行 MVP + Build-Measure-Learn

不是巧合。LLM 的默认行为正把过去 50 年我们用来抵抗自身缺陷的原则,逼着所有人重新用一遍------只不过这次不是用在自己身上,而是用在 AI 身上。

在 AI 时代,工程师的核心价值不再是写代码,而是为 AI 定义边界。

而那条边界,正是这篇文章前面六节讨论的所有原则。


八、结语

软件工程作为一门学科,从来不是关于"如何写出最完美的代码"------它是关于如何在不确定性、有限资源和不断变化的需求下,持续交付价值

这是 Knuth、Brooks、Fowler、Ousterhout、Ries 这几代人,用著作和案例反复在说的同一件事。

"优化怪圈"之所以隐蔽,是因为它产出的代码在局部看上去常常非常漂亮。它的真正危险在于:

它让我们用工程上看起来正确 的行为,回避了工程上真正困难的问题------价值判断、取舍、按时交付。

如果有一条贯穿始终的判断标准,或许是这一句:

优秀的工程不是把每一行代码做到极致,而是清楚地知道哪些代码值得被做到极致,哪些不值得,并且在两者之间保持冷静。


九、推荐阅读

如果文章里某个概念让你想进一步深入,下面是按类型组织的延伸资料。每一条都标注了它"能帮你解决什么问题",按需取用即可,不必通读。

起点:理解问题本身

  • Donald Knuth, Structured Programming with go to Statements(1974) 「过早优化是万恶之源」的原始出处。读完你会发现 Knuth 真正的论点比口号微妙得多------他要的是测量驱动的优化,而不是不优化。

  • Fred Brooks, The Mythical Man-Month(1975,中文版《人月神话(40 周年中文纪念版)》) 软件工程的奠基性作品。「没有银弹」和「概念一致性」两章,直接对应本文讨论的过度抽象问题。

方法论:怎么做才对

  • Martin Fowler, Refactoring(1999 / 2018,中文版《重构(第 2 版)》) Speculative Generality 的命名出处,也是 Rule of Three 的权威说法。配合实战可立刻识别项目里的过度抽象。

  • John Ousterhout, A Philosophy of Software Design(2018,中文版《软件设计的哲学(第 2 版)》,人民邮电出版社 2024) 300 页、两个晚上能读完。核心论点「复杂度是软件系统最持久的成本」是本文第二节的理论基础。

  • Kent Beck, Extreme Programming Explained(1999,中文版《解析极限编程》) YAGNI 第一次被确立为工程原则的现场。今天敏捷实践里一半的基础概念都来自这本。

  • Eric Ries, The Lean Startup(2011,中文版《精益创业》) MVP / Build-Measure-Learn 的源头。技术人的视角看会有点反直觉------但反直觉处往往是真相。

  • Robert C. Martin, Clean Code(2008,中文版《代码整洁之道》) Boy Scout Rule 的出处。提醒:这本书的某些具体建议(如"函数尽量短")今天已经被滥用并广受批评,但 Boy Scout Rule 这条本身仍然有效------只要你按本文第五节的方式正确使用它。

短读物:一两个小时能读完

现象与心理学背景

  • C. Northcote Parkinson, Parkinson's Law(1957,中文版《帕金森法则》) Bikeshedding 的概念发源地。读完会理解为什么大组织开会总把最多时间花在最不重要的事情上。

  • Tom DeMarco & Timothy Lister, Peopleware(1987,中文版《人件(第 3 版)》) 解释「为什么完美主义会偷走你的注意力」。1987 年写的,今天读依然准确------这本身就是一种警示。

相关推荐
零壹AI实验室5 小时前
GPT-5.5 vs 国产大模型:2026年5月AI编程工具横评实测
人工智能·gpt·ai编程
一心只读圣贤书5 小时前
QwenCode使用教程
程序员
明月_清风5 小时前
2026 前端生存指南:8 个正在重塑你职业生涯的技术趋势
前端·ai编程
亦暖筑序6 小时前
Spring AI Alibaba 1.1.2 实战:5种多Agent编排模式完全指南
java·spring boot·ai编程
不易_6 小时前
我的 AI 驱动开发工作流:基于 Cursor 的全流程实战开发方法论
前端·架构
洞窝技术6 小时前
低成本高可用:洞窝团队如何搭建 AI 协同开发环境
前端·ai编程
程序员cxuan7 小时前
Codex 官方:/goal 的正确打开方式
人工智能·后端·程序员
甲维斯7 小时前
MiMo2.5Pro《江湖百晓生》测试过程和结果!
人工智能·ai编程