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

新的构建方式需要一个能深入未知领域的通才,一个"压力下的快速学习者",而不是简历上那种注水式的说法。你实际上需要能够在与海怪搏斗的同时快速学习。这些年来我面试过很多人,当人们在简历上写"快速学习者"时,我喜欢请他们讲讲自己不得不快速学习一个复杂系统的经历,他们是怎么做到的?你的答案会是什么?
未来的所有者
所以基础是可以学到的,而广度是逐渐积累的。即时深度,然而,是可以练习的。这三大支柱正是让一个人能够在某个系统中扩大其所有权份额的关键。也许你从浅水区开始,把你的潜水机器人送下去。你拥有扎实的基础、不错的广度,那就去构建点什么吧。只是要做好准备,当东西出故障时,穿上潜水服,和怪物们一起游泳。
未来,谁来负责规模庞大的水下采矿作业?没人知道,但我敢打赌,会是那些能够驾驭上述三大支柱的人。会是那个拆开旧收音机并把它修好的孩子——他对收音机一无所知,只是渴望听音乐,哪怕把一切重新组装好之后多出了几颗螺丝。