夜雨聆风学习资料网

ARTICLE · 983734

AI写代码越快,软件可能死得越早:Go掌舵者Russ Cox谈透了软件工程的真问题

AI写代码越快,软件可能死得越早:Go掌舵者Russ Cox谈透了软件工程的真问题
现在谈AI编程,最常见的衡量方式是速度:以前一天写一个接口,现在半小时生成;以前两周搭出原型,现在一个晚上就能跑起来。但Go语言前技术负责人Russ Cox关心的是另一个问题:这批飞快生成的代码,半年以后谁还敢改?
Russ Cox不是站在岸边评论AI的人。他是Google杰出工程师,参与创建Go语言,担任Go技术负责人超过十年;在此之前,他做过Google Code Search,也开发了后来广泛使用的RE2正则表达式引擎。
2026年8月,ACM在《People of ACM》专访中请他谈Go、软件工程、AI编程和教育。他给出的判断没有“程序员即将消失”那么刺激,却更接近真实的软件现场:
AI不会推翻软件工程的基本规律,反而会逼我们重新学习那些早就知道、却总想绕过去的常识。

Go首先解决的不是语法,而是规模

很多人喜欢把Go概括成“简单、快速、并发友好”。Russ Cox说,这些特点不是孤立的审美选择。Go最初要解决的是2007年前后Google内部的软件工程问题:代码库很大,参与者很多,程序运行在大量联网机器上,每台机器又有多个处理器核心。
当代码规模、团队规模和机器规模同时膨胀,原有工具和语言暴露出的麻烦,不再是少写几行语法糖能够解决的。
所以Go从一开始就在做减法,一个典型例子是循环依赖,C++和Java的构建系统长期要处理库之间相互引用的问题。循环一旦形成,多个库就会绑成一个大块,只能一起分析、一起编译。工程师于是继续制造更复杂的构建工具,试图把这个复杂问题处理得更聪明。
Go选择了更粗暴的办法:禁止循环依赖。如果包A导入包B,包B就不能直接或间接导入包A。这条限制偶尔让开发者不舒服,却换来了更快的构建、更简单的静态分析和更容易理解的依赖图。
Russ Cox由此总结出一条经验:复杂问题的自然诱惑,是设计一个复杂答案;真正能扩展的办法,往往是先改变问题,把不必要的复杂性删掉。
Go里的许多设计都遵循这个逻辑,gofmt表面上是统一代码格式,真正的工程价值却不只是结束缩进和换行争论。格式由确定的算法控制后,goimports、gorename、go fix之类的工具就能自动修改源码,不会在提交记录里制造大面积无意义的格式变化。
Go还把完整导入路径直接写进源码,用URL式名称明确指出到底引用哪个包,避免几十个同名“uuid”包带来的歧义。所谓简单,不是功能少,也不是代码短,而是主动消灭团队长期协作中反复出现的分歧、歧义和隐藏成本。

编程解决今天,软件工程负责明天

Russ Cox对软件工程有一个著名定义:“软件工程,就是给编程加上时间和其他人。”
一个人写程序,运行成功,拿到结果,事情可以结束。但如果这段代码要连续运行几年,还要不断修改需求;如果五个、五十个甚至几百个工程师都要碰它,问题就变了。
版本控制、缺陷跟踪、自动测试、模块边界、设计模式和代码审查,并不是给编程添加的官僚手续,而是为了让代码跨越时间、跨越人员变动后还能继续工作。
这也解释了他为什么说:“测试更多是为了明天,而不是今天。”
如果只关心今天能不能运行,手工点几遍页面也能确认。麻烦在于,明天要升级编译器,下个月要替换依赖,半年后要重构核心模块,新同事还会提交自己并不熟悉的改动。
每次都靠人重新猜测“哪里可能受影响”,项目规模一大就会失控。自动化测试真正保护的,是系统已经承诺过的行为。测试越完整,团队越敢升级、重构和接受外部修改。这个“外部修改者”现在还包括AI编程Agent。一个不了解系统历史的人或Agent能否安全提交代码,很大程度上取决于测试能否迅速指出它破坏了什么。
Russ Cox在博客《Go Testing By Example》中列了20条测试建议,其中最值得留下的不是技巧,而是几条纪律:
让新增测试用例足够容易;用覆盖率寻找盲区,但不要把覆盖率当成思考的替代品;主动寻找特殊情况;让失败信息一眼可读;持续改进测试;如果没有补测试,就不算真正修复了Bug。
“代码质量受测试质量限制。”在AI生成代码越来越便宜之后,这句话会比过去更贵。因为代码产量上升得越快,人工逐行理解所有改动就越不现实,测试会从质量辅助工具变成团队接收机器产出的安全边界。

免费依赖不是免费代码

AI不是第一个让代码获取成本骤降的工具。包管理器早就完成过一次类似革命。
Russ Cox在《Our Software Dependency Problem》中提到,2019年的NPM已经托管超过75万个包。其中一个叫escape-string-regexp的包,核心实现只有8行,用来转义正则表达式特殊字符,却被近1000个其他NPM包直接依赖。
包管理器把下载和安装代码的成本压到了接近零,于是连一个函数都值得单独发布。开发者只需敲一条命令,就能复用陌生人写好的设计、实现和测试。
问题是,安装成本接近零,不等于持有成本接近零。引入一个依赖,实际上是把设计、编码、测试、修复和未来维护外包给互联网上的另一个人。
依赖里出现漏洞、兼容性问题或维护者变动时,承担生产事故的仍然是使用它的团队。Russ Cox的说法很直接:我们正在信任越来越多的代码,却越来越缺少信任它们的理由。
这与AI生成代码的风险高度相似。代码出现在仓库里的那一刻看起来很便宜,真正的账单在以后:谁理解它,谁验证它,谁修补它,谁为它与整个系统不一致负责。
因此,选择依赖不能只看下载量和“能不能跑”。要检查API设计是否清晰、文档是否说明兼容边界、测试能不能运行、缺陷是否长期无人处理。
对AI代码也一样,不能因为它生成得快,就降低进入主干的门槛。来源改变了,责任没有转移。

AI最危险的角色:终极“战术龙卷风”

Russ Cox并不认为AI会在某一天制造一次不可理解的编程革命。他更愿意用“连续变化”描述AI的影响。就像今天的电脑与20世纪80年代的电脑几乎处处不同,但变化是由许多个小台阶累积而成,AI也会一点点进入编码、测试、审查和维护,最后让工作方式发生质变。
这个判断很重要,因为它意味着人并非只能等待冲击。团队仍有时间决定AI适合做什么、不适合做什么,以及什么环节必须由人掌握。他引用了Peter Naur 1985年的论文《Programming as Theory Building》。
Naur认为,维护一个程序不仅需要读懂代码,还需要掌握一套关于“现实需求如何映射成程序结构”的内在理论。这套理论不可能全部写进文档。它最有价值的部分,恰恰体现在遇到意外新需求时,团队知道哪里应该改、哪里不能动,以及怎样用最小代价保持系统一致。
Naur有一句很重的话:当掌握程序理论的团队解散时,程序就已经死亡。这个“死程序”可能仍在服务器上运行,也可能继续产生有用结果;死亡真正暴露出来,是新的修改要求出现后,再也没有人能聪明地回答它。
这正是当前AI Agent的软肋,它可以读一批文件,在一次会话里产出能够运行的代码,却通常没有长期记忆,也没有持续形成并维护系统理论。
它像一个精力旺盛的新工程师,能完成眼前任务,却容易加入不必要的抽象、重复路径和局部补丁。每次修改都能跑,整个系统却越来越难解释。
软件设计专家John Ousterhout把只追求“今天先跑起来”的方式叫战术编程,把愿意为长期结构投入时间的方式叫战略编程。
他还创造了一个形象的词:“战术龙卷风”。他用了一个很准确的比喻:“去健身房时带一台叉车,并不能帮你长出肌肉。”AI当然可以跳过一些不重要的机械劳动。但凡课程或工作真正希望人掌握的能力——建立模型、定位问题、权衡设计、形成系统理论——因为能力往往就长在那些不舒服的地方。

AI时代真正稀缺的,不再是代码

把ACM专访与Russ Cox多年的博客放在一起看,会发现他的观点始终指向同一件事:软件行业最难的部分,从来不是把字符输入编辑器,而是让一套系统在时间、人员和需求不断变化时仍然保持清晰。
Go用限制换取规模,用统一格式换取可自动修改,用无环依赖换取可理解性;测试把今天的行为保存给明天;依赖审查提醒我们,获得代这些原则不会因为代码改由AI生成而失效。对团队来说,正确的AI策略也因此很具体:让Agent处理边界清楚、结果可验证的任务;重要改动必须带测试;审查时不只问“能不能运行”,还要问它是否符合现有模块边界和设计时补丁;为系统保留能够解释“为什么这样设计”的人。
AI会继续降低写代码的价格,但它不会自动降低理解、验证和维护代码的价格。恰恰相反,当代码供给突然过剩,判断哪些代码不该进入系统,会成为更重要的工程能力。以前,团队担心程序员写得不够快。接下来更现实的风险是:代码来得太快,快到没有人来得及理解它。
原文来源:
ACM《People of ACM:Russ Cox》
https://www.acm.org/articles/people-of-acm/2026/russ-cox
Russ Cox个人博客
https://research.swtch.com/

相关学习资料