当智能体替你写代码:软件工程中的“此处有怪物”
Here be monsters: What do you still need to know when agents do the work?
一位开发者让 Codex 迭代 App.tsx,Codex 把多个完整组件各写在一行里,触发 SonarQube 圈复杂度告警,最终通过重构拆成 10 个文件才让 CI 通过。作者由此提出,智能体产出代码的速度远超人类吸收速度,未来维护系统更依赖“知道何时有问题、并能按需深入”的能力,而非亲手写代码的经验。
CI 失败了。这出乎意料。我已经把我的智能体工作流调校到这种程度:如果我的某个智能体提交的分支带有失败的测试,我会感到惊讶。也许是 CI 偶发故障或环境问题?等等,是 SonarQube 在抱怨 App.tsx?我们是不是从 npm 引入了什么新的可疑依赖?没有。SonarQube 是在标记这个文件的圈复杂度。好久没见过这个了。
没错。App.tsx 大约有 30 行代码,只不过其中 15 行实际上是 Codex 决定各自写在一行里的完整组件。这本身倒没什么,跑一下 prettier 就完事了。但这解释不了圈复杂度。这些组件每一个都相当复杂,带有大量展示和业务逻辑。过去的我会仔细重构,确保代码可读。而另一方面,Codex 不在乎整个组件写在一行里,更重要的是,它不在乎复杂度。它一直愉快而可靠地在这个文件上迭代,实现了好几个功能。
CI 工具在标记一个问题,也许对,也许不对。但这是一个真实系统,所以我必须深入排查。格式化文件后,我逐一检查了组件和逻辑。Codex 是否超出了典型开发者在覆盖边界情况方面的做法,并且稍微过度设计?是的,但全都是正确的。我没什么可抱怨的。所有复杂度都是业务需求所必需的。所以我让 Codex 去让 SonarQube 满意,它通过重构并把东西拆分成 10 个文件做到了。CI 通过了;东西上线了。虽然这次事件很快解决了,但你大概能想象情况本可能糟糕得多。毕竟,这是我从未见过的代码。
这就是我们行业的发展方向:拥有一个软件系统将越来越少地依赖于亲手编写它(或类似系统);相反,最重要的是知道刚好足够多,能在出问题时察觉不对劲,并且愿意也有能力在需要时深入所需深度。
潜水机器人与金块
想象你在一艘船上(船的类型随你挑),你的工作是从海底收集小金块。直到最近,如果你想拿到一袋金子,你得跳进水里,游到海底,四处寻找,然后把袋子装满。在清澈的浅水区这轻而易举,但你能想象这很快就会升级成困难得多的事情。于是,随着浅水矿藏开始枯竭,你和工程师同伴们建造了各种机械和工具,从越来越深、越来越危险的水域中开采黄金。这在大多数情况下行之有效,你和你的团队会小心地组装、维护、轮换这些机械,并不断潜入海底采矿作业区维持其运转。时不时你会听说某个采矿作业坍塌,有时是因为巨大的水下压力,有时是事故,或是操作员无能。挑战在于这是一个地质活动非常活跃的世界,所以海床不断变化,一些矿藏枯竭,新的矿藏又在不同地方冒出来。
不过有个好消息!过去几年里,潜水机器人(divebots)变得越来越精密,它们能下潜并自行搭建采矿作业。你只需告诉它们在哪里建造,它们就会潜入水下,只在浮上来时向你汇报进展并带回金块。一切都很美好,你现在可以悠闲地待在船上,让潜水机器人干活,唯一要操心的就是能往船上塞多少金子。这就是乐观派阵营。
直到……
“等着吧,你的潜水机器人潜得太深然后迷路了。”“哈哈,你的潜水机器人带回来的东西看着像金子,其实是闪闪发光的章鱼粪便。”随着潜水机器人越来越多,你看到越来越多恐怖故事。潜水机器人迷路,忘了自己该建什么。潜水机器人造出了极其复杂又怪诞的东西,自己都难以维护,结果被下一代潜水机器人丢弃。所有水下采矿作业都从精心设计、工程严谨的大教堂,变成了杂乱无章的豪宅,里面藏着隐秘通道和潜伏的恐怖。你离作业越远,失败就越壮观。这就是怀疑派阵营。
此处有怪物
软件工程行业(我猜很快还有许多其他行业)正在经历上述情景的一个版本。你大概已经知道自己更符合怀疑派还是乐观派,哪怕你还不确定自己想加入哪个阵营。
传统智慧认为,要开发和维护一个非平凡的系统,你需要对它有一个正确的工作模型。我想很少有人会对此有异议。而在软件工程中,你要通过直接与代码打交道来获得这个工作模型。多年乃至数十年编写和阅读代码的实践,赋予了你理解和负责系统所需的知识与工具。每一次生产事故、每一次深夜调试、每一次成功发布。所有这些经历都给了你拥有一个系统所需的视角。在本文语境中,拥有意味着出问题时,你就是那个被叫来处理的人。
智能体(潜水机器人)正在把这一切彻底颠覆。潜水机器人产出成果的速度远超任何人能吸收的速度,而在过去的复杂系统中,你可以假定代码至少曾经过某个人的手,如今这已不再成立。现在,经验丰富的从业者可以管理成群的潜水机器人,以前所未有的规模创建软件。这些操作者深谙此道,凭借丰富的经验来管理和架构过去需要团队才能构建的大型系统。但这暴露了我们行业可能面临的最大挑战:我们该如何培养下一代工程师?
在极端情况下,乐观主义者和怀疑论者对这个问题的答案截然不同。一方面,有可信的声音说,要维持对这些系统的控制,唯一的方法就是阅读 divebots 产出的每一行代码。要能够手写代码。要能够解释每一段代码的作用,以及它如何融入应用程序的上下文。在另一个阵营,同样有可信的声音说,甚至不必费心去看代码。把精力集中在弄清楚要构建什么,忘掉它是如何构建的。模型会处理好的。我认为这两种观点都不对。
事实是,当今资深工程师学习的方式,即通过手写代码、无数小时的调试、生产事故等,对今天的初级工程师来说并不是一条可行的路径。需要明确的是,这在经济上不可行,这意味着公司极不可能愿意资助初级工程师数年,让他们“学习手写代码”。那是一厢情愿的想法。经常被提出的另一种建议是“确保你理解你的智能体写下的每一行”,或者“与资深工程师结对”,或者“进行仔细的代码审查”。同样,除了少数几家公司外,这都是一厢情愿。如果你认为整个行业会采纳这些做法,那我有一座桥要卖给你。联系我。
为了找到一条可行的路径来实现某种程度的精通,我们必须审视拥有一个非平凡软件系统意味着什么。如果你想想典型的架构师/技术负责人/CTO 以及他们如何运作,就会清楚,要成功,他们需要在头脑中有一个系统的模型,一张水域图。真正的问题是在什么粒度级别?想象一个遗留的百万行代码库,它多年来由许多人编写和扩展。CTO 甚至可能写过其中的部分代码。现在想象出现了一个生产问题,而你就是那个倒霉的 SRE,在凌晨 2 点试图弄清楚这个问题,同时还要接收来自不同时区的人发来的愤怒短信。你需要什么样的系统地图?你需要一张整个系统的高层、远观地图,你需要知道刚好足够的信息,以知道你需要在哪里深入,怪物住在哪里,并且你需要能够跳进任何未知的代码库,弄清楚发生了什么,推送一个热修复,并在事故报告中清楚地描述发生了什么。
请注意,这不是对整个系统的详细知识。我们管理复杂系统的唯一方法就是建立抽象。每一层都让我们能多构建一点,但无论你拥有什么地图,重要的是要记住,抽象层层递进,没有人真正理解所有层次。“我写了模块 X 并对它了如指掌”和“我对系统抽象有适当的模型,能够深入任何模块并在它出问题时修复它”之间有很大区别。手写代码给了我们前者,但系统的所有者,那个被叫来的人,需要的是后者。
那么这张图是如何建立起来的?如果一个人从未亲手淘过金块,又怎么能指望他潜入未知水域,修复 divebots 造成的烂摊子?
基础、广度与即时深度
复杂系统中最隐蔽的一些故障是静默故障。就是那种大部分时候都能正常工作,但系统总有点不对劲的情况。也许是突然变慢了,或者错误率上升了,又或者绝大多数时候都运行完美,但每第 19 次尝试就会失败。还没到凌晨 2 点被叫醒处理的程度,但足以让你感觉有什么地方不对。作为系统的负责人,你需要理解系统的故障模式。作为一个行业,我们拥有教人们如何检测和推理这些故障的工具:基础知识。好消息是,几十年来我们一直在把这些知识教给那些浑然不觉的计算机专业学生。我说的是数据结构和算法、网络、并发、分布式系统等等。这些也不一定非得来自正规教育,这些都是你可以自己阅读和学习的话题。
举个简单的例子(如果你是资深工程师,请在此包涵一下),想象你派你的潜水机器人去执行任务。你在浅水区,把它送到水下 2 米去收集一些金块。它 4 秒后回来了,一切正常。接下来,你把它送到水下 4 米。但这一次它花了 16 秒。这很奇怪。下一次任务是下潜 16 米,花了 256 秒。你明白了吧。显然有什么地方不对劲。在计算机科学中,这被称为平方复杂度,而识别它的最佳方式可能就是理解相关理论,并知道存在这样一种东西。
这就引出了系统负责人的下一个支柱:广度。我有幸共事过的大多数成功工程师和工程领导者,都能就几乎任何话题展开讨论,无论是否与技术相关。他们可能是某些领域的专家,但最令人印象深刻的是他们能够借鉴并糅合来自不同学科看似毫不相关的概念,并用这些知识来解决问题。这是水域的高层地图。正是它告诉你某些海域比其他海域更危险。知识的广度让你能够说出“我们在这里下潜吧”。需要说明的是,我指的不是对每个可以想象的领域都具备专家级知识,而只是足以知道当事情不对劲时该去查什么。这些就是指引你探索海洋的浮标。
有人问我“我们怎么教广度?开一门涵盖一切的概览课?”我当时没有好的答案。但进一步思考之后,我觉得这不是能教出来的东西。没有什么“万物入门 101”可以选修。我们最多能做的就是鼓励人们去阅读、去探索、保持好奇。尽可能多地吸收信息。记住那些奇怪的事件、那些“糟糕”的时刻,思考它们如何与你的工作相关联。随着你积累更多经验,要有意识地把你日常的经历与工作联系起来。我已经记不清有多少次,多年前在一个随机项目中学到的那一点知识突然冒出来拯救了局面。这种经验和广度会不断累积,但必须加以维护。
拥有权的最后一个支柱是我所说的即时深度。这是一种能力和意愿,能够深入任何问题并把它弄清楚。即使你身处未知水域。即使你必须进入笼子,和鲨鱼一起游一会儿。即使你必须召集你的团队,装载大型专用潜艇,潜过巨型鱿鱼,去弄清楚系统出了什么问题。这就是愿意学习完成任务所需的一切。这也是谦逊,知道什么时候一次下潜超出了你的能力,需要寻求帮助。不是每一次下潜都能独自完成;也不是每一次下潜都值得去做。
几个月前,在开发我的 agent 编排器时,我的 agent 和子 agent 遇到了稳定性问题和生命周期 bug。我知道我想让它们做什么,但构建这个东西的 divebot 做得相当随意,所有 bug 一下子全冒了出来。当我坐在屏幕前,看着我的 agent 在一小时内第 n 次崩溃,并且在让 divebot 修复它们自己造成的烂摊子几次失败之后,我想起多年前读过一本 Kubernetes 的书(是的,我是个书呆子),突然,“电平触发状态机”这几个字就摆在了我面前。于是我进行了一次下潜,比我原本打算的更深,甚至一直追溯到“电平触发”的电气工程起源。我带着我的 divebot 一起,从头重新设计了核心架构。从那以后,它一直坚如磐石。这次成功的重写之所以可能,主要是因为我想起了多年前读过的东西,并且愿意深入下去,学习完成任务所需的一切。
所以你从海洋(系统)的高层地图开始,并理解它一路到底都是层层抽象。而由于所有这些抽象都会泄漏,你作为系统所有者的工作就是知道在哪里下潜以及潜多深。这不再是通才与专才之争,甚至也不是神话般的 T 型人才。

新的构建方式需要一个能够深入未知领域的通才,一个“压力下的快速学习者”,而不是简历里那种注水说法。你真的需要能够在与海怪搏斗的同时快速学习。这些年来我面试过很多人,当人们在简历里写“快速学习者”时,我喜欢请他们讲一次他们不得不快速学习一个复杂系统的经历,他们是怎么做的?你的答案会是什么?
未来的所有者
所以基础知识可以学习,广度可以积累。而即时深度则可以练习。这三个支柱使一个人能够扩大其在系统中的所有权份额。也许你从浅水区开始,把你的 divebot 派下去。你有扎实的基础知识、不错的广度,那就去构建一些东西。只要准备好,当东西坏掉时穿上潜水服,和怪物一起游泳。
未来谁来负责那些不断扩张的水下采矿作业?没人知道,但我敢打赌,会是那些能够运用上述三个支柱的人。会是那个拆开旧收音机并修好它的孩子,他对收音机一无所知,只是渴望听音乐——即使他们在把所有东西装回去之后,确实多出了几颗螺丝。
来源:Hacker News · blog.adrq.dev