少即是多

当AI让代码变得充裕,更难的工程判断,是决定哪些代码值得留下。

Pluralitas non est ponenda sine necessitate.

如非必要,勿增实体。

奥卡姆剃刀的这句表述原本属于哲学,而非软件工程。然而,在与AI一同编写和审查代码时,我愈发觉得,它正是我最需要遵循的原则。

在软件发展的绝大部分时期,产出代码是一件昂贵的事。每增加一项功能,都需要有人想清楚逻辑、写下实现、排查问题,并向他人解释。创造的成本,天然地带来了克制。

大语言模型消除了其中的大部分摩擦。

只需提出一个小功能,模型就可能生成组件、辅助函数、校验层、错误处理、配置项、默认值、测试、注释、抽象,以及对若干假想未来场景的支持。乍看之下,结果令人印象深刻:面面俱到,像是经过了周密的工程设计。

但再仔细看一遍。

你会发现,为永远不可能发生的情形写下的分支;没人要求的默认值;掩盖非法状态、却不阻止它出现的兜底逻辑;只使用过一次的“可复用”抽象;为了少写十行直白代码而引入的依赖。代码确实能运行,但解决方案的规模已经超过了问题本身。

模型完成了任务,却未必理解这个任务不该包含什么。

只增不减的代码库

GitClear在其2026年软件变更分析中,提出了一个不断扩大的 “可维护性缺口”。报告认为,当前AI工作流优化的是一次性的完成:测试通过、功能可用、工单关闭;而整合工作和长期维护责任,却没有得到足够重视。(GitClear)

这与我的经验相符。

智能体通常只是在解决眼前可见的请求。它不会自然而然地为整个仓库的概念负担负责。新增一个辅助函数,往往比修改已有函数更稳妥;新建一个组件,可能比理解现有组件为何存在所需的上下文推理更少;处理一个非法状态,也可能比重构模型、让这个状态根本无法出现更容易。

Armin Ronacher最近形容当下的编程模型,其推理方式 过度防御、过度复杂,也过于局部。它们倾向于增加兜底和局部保护,而不是建立强有力的不变量。他认为,若将这种行为置入自动化循环,每一轮迭代都会再叠加一层小小的防御,系统表面上更健壮,实则越来越难理解。(Armin Ronacher’s Thoughts and Writings)

这正是AI生成软件的悖论:它看起来越来越完整,却也可能越来越难以理解。

生成之后的工作

AI能实现功能、通过测试、关闭工单。这当然有用,但它不等同于把系统工程化为一个值得长期维护的作品。

更难的工作,是决定什么应该留下。

哪些东西可以删掉?哪些检查对应真实需求?两条路径能否合而为一?非法状态应该被处理,还是应该从设计上变得不可能?一个抽象是在简化系统,还是又引入了一个概念?

增加代码只需要局部上下文。删去一个兜底逻辑,或合并两套实现,则需要理解系统的不变量与架构。

这也是为什么,用产出来衡量AI生产力很不可靠。生成得更快,不代表完成得更快。审查、修正和整合生成结果,正在消耗我们表面上的时间收益。代码更多,也不一定代表系统更好。

原则:如非必要,勿增实体

因此,奥卡姆剃刀成了我与AI协作编程时的指导原则。

AI生成的代码很容易把实体、函数、类、依赖和抽象不断增加,远远超出问题所需。输出看似完整,额外的复杂度却让代码库更难理解、更难维护。

“少即是多”并非为了少写代码而少写代码,而是关乎意图。 每一行都应当证明自己存在的理由;每一个抽象都应当配得上它占据的位置;每一项依赖都应当服务于真实需求。

这也是大语言模型最需要引导的地方。在需求尚未被真正理解前,它们很容易生成投机性的功能、防御性的检查和不必要的封装。工程师的职责,是决定什么属于系统,什么不属于。

审查时,先找可删之处

当一个很小的请求换来一份庞大的生成式改动时,我不会先逐行阅读。我会先用具体的语言重述所需行为,并以此作为筛子:为了交付这个行为,究竟需要哪些文件、分支、配置和依赖?

接着,我会沿着改动的主路径追踪:数据从何处进入,如何转换,最后什么结果抵达用户。凡是不服务于这条路径的代码,都需要说明自己为何存在。一个新的辅助函数、选项、兜底逻辑、抽象或依赖,都应该回答一个简单的问题:哪项真实需求使它成为必要?

测试通过只是第一道关卡。它证明代码能够工作,却不能证明每个分支、默认值或层次都值得保留。改动正确之后,我会专门进行一轮精简:移除未使用的路径,合并重复逻辑,舍弃投机性的选项,并尽可能以更强的不变量替换局部防御。

这不是要求行数越少越好。过分聪明的压缩同样会掩盖领域逻辑,正如生成式代码的臃肿会遮蔽逻辑一样。只要能让系统更清晰,较长的实现反而更好。

目标是必要的代码:保留一切清晰表达系统所必需的内容,不留下任何仅仅因为生成容易而存在的东西。

大语言模型让代码变得充裕。工程师的角色不再只是产出一个实现,更是决定什么值得留下。

Pluralitas non est ponenda sine necessitate.

不要增加系统并不需要的东西。