懒惰的美德:当AI不再懂得偷懒的艺术
前言
最近读到两篇很棒的博文,让我对 AI 时代的编程有了更深的思考。
一篇是 Bryan Cantrill 的《The peril of laziness lost》(失去懒惰的危险)。Bryan 是 DTrace 的作者、Oxide Computer 的 CTO,系统编程领域的传奇人物。
另一篇是 Mario Zechner 的《Thoughts on slowing the fuck down》(关于放慢脚步的思考)。Mario 是 libGDX 游戏框架的创建者,也是一位经验丰富的开发者和教练。
两位作者从不同角度提出了同一个警告:在 AI 编程时代,我们正失去一些宝贵的东西。
Larry Wall 的三美德
要理解他们的观点,得先回到 Larry Wall。
Larry Wall 是谁?Perl 语言的创造者。他在那本著名的《Programming Perl》(被亲切地称为”骆驼书”)里,提出了程序员的三美德:
懒惰、急躁、傲慢
原文是这么说的:
如果我们要讨论好的软件设计,就必须谈到懒惰、急躁和傲慢。这些都是好软件设计的基础。我们都曾掉进复制粘贴的陷阱,其实应该定义更高层的抽象,哪怕只是一个循环或子程序。当然,有些人走向了另一个极端,定义了越来越多的高层抽象,其实应该用复制粘贴。但一般来说,我们大多数人需要思考的是使用更多抽象,而不是更少。
懒惰的真正含义
这里的”懒惰”不是贬义词。
它是一种工程智慧:
- 懒得写重复代码 → 所以抽象出通用模块
- 懒得维护复杂系统 → 所以追求简洁设计
- 懒得处理边界情况 → 所以在设计时就考虑周全
Bryan 说得很好:
这种看似懒惰的背后,其实是在脑子里反复思考问题。我们承担开发抽象所需的艰难智力工作,部分原因是我们正在优化假设中的未来自己的时间,即使以牺牲当前时间为代价。
这就是 hammock-driven development (吊床驱动开发)的精髓——看似在偷懒,实则在深度思考。
LLM 的问题:不知疲倦的”勤奋”
现在问题来了。LLM 不会累,也不需要优化自己的时间。
Bryan 举了一个例子:Garry Tan(Y Combinator 的 CEO)炫耀自己用 LLM 一天写了三万七千行代码,而且”还在加速”。
对比:整个 DTrace 项目大约也就六万行代码。
这意味着什么?
一位波兰工程师 Gregorein 解剖了 Garry Tan 的”newsletter-blog-thingy”项目,结果让人啼笑皆非:
- 包含多个测试框架(?!)
- 包含 Rails 的 Hello World 应用(?!)
- 偷偷塞进去一个文本编辑器
- 八个不同版本的同一个 logo,其中一个文件大小为零字节
错误在复合:Mario 的警告
Mario Zechner 从另一个角度提出了更严峻的警告。
他说现在的软件”一切都坏了”——98% 的正常运行时间反而成了常态,界面有各种奇怪的 bug。虽然这不能全怪 AI,但趋势在加速。
复合的”小错误”
Mario 提出了一个很形象的词:booboos(小错误)。
人类也会犯错,但:
- 人类会学习,不会重复犯同样的错误
- 人类是瓶颈,一天能写的代码有限
- 当痛苦积累到一定程度,人类会去修复
但代理(Agents)不一样:
- 代理没有学习能力(除非你显式教它,但它还是会忘)
- 代理没有瓶颈,几小时能生成几万行代码
- 代理不会感到痛苦,所以你不知道错误在积累
这些小错误(重复的代码、无用的方法、错误的抽象)会在代理手中指数级复合。直到有一天,你想加个新功能,发现架构已经烂到无法支持;或者用户数据被删除了,你才发现问题。
复杂性的商人
Mario 还有一个很犀利的观点:代理是“复杂性的商人”(merchants of learned complexity)。
代理在训练数据中见过太多糟糕的设计决策。当你让它们帮你设计架构时,它们会引入大量复杂性——各种 Cargo cult 的”行业最佳实践”、为了抽象而抽象的代码、不一致的重复实现。
更糟糕的是,代理只有局部视野。它们看不到整个代码库,看不到之前的决策,所以总是在局部做”看起来对”的选择,最终导致全局的混乱。
Mario 说:”一个 2 人团队用代理,几周内就能达到传统企业代码库的复杂度。”
低召回率的代理搜索
Mario 还指出了一个技术问题:代理搜索的召回率很低。
当代理试图重构或修复代码时,它需要先找到所有相关的代码。但无论是用 ripgrep、LSP 服务器还是向量数据库,当代码库变大时,代理总会遗漏一些代码。
结果就是:
- 遗漏现有代码 → 重复造轮子
- 遗漏相关代码 → 修复不完整
- 遗漏上下文 → 引入新的不一致
这就是那些”小错误”产生的根本原因。然后它们会像滚雪球一样,变成一朵“美丽的屎花”(shit flower)。
为什么这很危险
把这两篇文章放在一起读,我觉得他们说的是同一件事的两面:
LLM 不会感到需要为自己(或任何人)的未来时间做优化,它们会毫无顾虑地在一层又一层的垃圾上堆叠更多垃圾。
如果不加以约束,LLM 会让系统变得更大,而不是更好——可能迎合了某种扭曲的虚荣心指标,但代价是牺牲了一切真正重要的东西。
最好的工程总是源于约束,而我们人类时间的约束限制了我们对系统认知负荷的容忍度。正是这种约束驱使我们让系统更简单,尽管系统本质上就很复杂。
放慢脚步:我现在怎么做
基于两位作者的观点,我总结了几条实践建议:
1. 限制代码生成量
Mario 建议:给自己设定每天生成代码量的上限,与你能 review 的能力相匹配。
不要追求 37k 行/天,追求 100 行高质量的代码。
2. 手写架构,代理实现
架构、API 设计这些决定系统”气质”的东西,必须手写。
用 tab 补全感受代码的构建过程,或者用结对编程的方式和代理一起写。这种摩擦能让你更好地理解系统在”感觉”上是否正确。
3. 把 LLM 当实习生用
它可以帮你写代码,但你需要 review、refactor、甚至重写。
好的代理任务应该是:
- 范围有限,不需要理解整个系统
- 有明确的评估标准(可以自动验证结果)
- 不是关键路径,不会导致数据丢失
4. 追求”少即是多”
当 LLM 给你一大坨代码时,问它:”能不能更简洁?”
学会说”不”本身就是一种能力。做更少的功能,但做对的功能。
5. 保持批判性思维
LLM 生成的代码往往”能用”但”不够好”,别被数量迷惑。
定期重构,防止技术债务累积。如果你连自己写了什么都不知道,当出问题时就无法修复。
结语
Larry Wall 说懒惰是美德,这是一种智慧。
Bryan Cantrill 提醒我们,这种美德在 AI 时代变得更加稀缺。
Mario Zechner 告诉我们,如果不放慢脚步,我们会被代理带入一个复杂性的深渊。
机器不会累,不会觉得麻烦,不会为了追求简洁而绞尽脑汁。这些人类的”弱点”,恰恰是创造力的源泉。
这不是说不该用 AI 工具。而是说:为了将来能少做一点,现在要多做一点思考。
这种”懒惰”,才是真正的懒惰。
参考阅读: