读代码,还是不读?

作者:Kieran Klaassen | 原文:To Read—Or Not to Read the Code? | 日期:2026-09-08


我现在的产出比以往任何时候都多,但我感觉自己的脑子变钝了。

过去一年,我一直在寻找编码过程中仍然需要我的部分,然后用能完成这件事的东西取代自己——无论是一项技能、一个框架、一个数据源,还是一个把工作路由给下一个 agent 的步骤。这就是复合工程(Compound Engineering)的本质:教会系统一次,它就永远替你完成。我正是用这种方式构建 Cora,Every 的邮件助手;纵观整个职业生涯,我认为这是自己做过的最好的产品与工程工作。

但不知从什么时候起,我发现失去了一种感觉。从前,学习本身就是奖励。而如今,我的大脑越来越像 TikTok 信息流——充满短暂的快感,却什么也留不下。

我开始注意到,工作虽然在变好,我却没有跟着变好。自己的头脑成了这套系统中我忘记测量的部分。

于是,我在系统里又加了一条循环——在理解上的缺口变成判断上的盲区之前,先把它填上。

黑暗工厂会熄灭你脑中的灯

构建产品时,给 AI 让路通常是正确的选择。当你是系统中最慢的部分时,绕开自己是合理的。但如果脑子里只想着产品,你就是在忽略自己的成长。

“黑暗工厂”(dark factory)描述的是制造业自动化的理想状态:关灯、车间无人、机器整夜运转。但当你自动化自己的工作时,风险在于,你同时也会熄灭自己脑中的灯。

大量工作本应在黑暗中运行。当我们重建 Cora 收件箱的一部分时,发现行与行之间的间距小了 4 像素。让 agent 诊断 bug、恢复间距、写测试、打开 pull request——那包等待审查的代码变更——都很简单。我的理解不会改变这个决定。但无论如何,理解它仍然重要。

大量工作看起来是机械性的,直到你理解得足够深,才会看见其中藏着的决策。这些地方,就是我想让灯继续亮着的地方。

读代码,是为了学习

去年,我写过一篇关于自己在 code review 中不再逐行读代码的文章。现在依然如此——我读代码不是为了验证工作。规划、测试和 review 的 agents 比我处理得更好。发生变化的是,最近我又开始读代码了。不是检查工作,而是学习。如果你打开 diff(逐行显示变更的视图)的唯一理由是怀疑,那再怎么用力读,也修不好你的流程。

举例说明:今年 7 月,我让 /ce-explain——一个我自建的命令,会顺着我的代码库追踪某个概念或变更来解释它——带我走一遍 Cora 如何把 Gmail 里的一次变化变成用户能看到的东西:Gmail 标记变化,Cora 等一等,让相关变化一起到达,然后逐条处理一批消息。那一次讲解,把几十个零散的细节变成了一幅我能装进脑子里的图景。

两周后,正是这幅图景让我分辨出:一个修复听起来是对的,还是真正是对的。有客户报告说,Cora 永久删除了他已经发出的邮件——他的审计日志显示多次删除,其中一次就在他点击 Send 后几秒。我怀疑是最近一次加速让系统的两个部分撞在了一起,结果我猜对了:一个让清理过程大幅提速的改动,暴露了一个已经存在好几个月的 bug。

这一次,我让 /ce-explain 指向故障而不是功能,请它还原发生了什么。Cora 曾在 Gmail 里创建了一封草稿,并保存了它的地址以便稍后清理。客户打开了同一封草稿,编辑并发出了它。保存的地址仍然有效,但 Cora 的清理过程无法知道这封草稿已经不再是草稿,于是仍然删掉了这条消息。最初提出的修复方案听起来都很合理,但都是错的:等 30 秒再删,或者如果 Cora 刚刚自己发出过这封草稿就跳过删除。两者都不符合实际情况——客户是通过 Gmail 发出的,不是通过 Cora,所以没有可检查的信号;而 30 秒只是对 Gmail 时机的猜测。我坚持采用的是一条不做猜测的规则:删除前直接问 Gmail,它是否仍然是草稿;如果 Gmail 无法确定,就什么也不删。规则上线几小时内,它就经受了真实测试:同样的危险情况再次出现,这一次,这道防护拒绝继续执行。

我不需要读修复的每一行代码。我需要足够理解这个系统,才能认识到:一个听起来合理的答案,并不等于一个安全的答案。

这才是你在智能体工作流(agentic workflow)中贡献的东西:不是代码,而是判断力——知道把 agent 指向哪里、何时阻止它,以及两个听起来都合理的方案中,哪一个会在六个月后伤到你。放任不管,判断力不会自动维持,而会不断被侵蚀。

代码库是从底层开始复利的。如果一个人没有和代码库一起复利,两条曲线就会开始分岔:系统越来越强大,而人评判它的能力越来越弱。

这可不是随便的观察。研究人员 Margaret Mitchell、Avijit Ghosh 和 Samir Passi 在最近一篇论文中回顾了相关证据,发现了一个一致的模式:长期使用 AI agents 会可测量地侵蚀人类监督所依赖的警觉性、批判性思维和领域技能。AI agents 是新的,但这种现象不是。早在 1983 年,一位研究自动化工厂和发电厂人类操作员的安全研究员就把它称为“自动化的反讽”(the irony of automation)。自动化能力越强,人类的技能退化越严重。Agents 只是让这一切发生得更快了。

我让“人”持续复利的四种方法

判断力和代码库一样,是靠一点一点积累理解建起来的。以下是我日常的做法。它们都不依赖 Cora、/ce-explain 或任何特定工具;你已经在用于自己代码库的任何 agent 都适用。

1. 重新打开 Files 标签页,并保留一份清单。 重新查看一个你当时没有读就合并的 pull request。当你遇到不认识的东西——一个模式、一个库、一个你不会这么写的调用——问模型为什么选择这个方案。你不需要理解每一行。注意到每一个不理解的地方,并把那些缺口当成你的学习清单。

2. 问机制,而不是 diff。 大多数变更依赖 diff 不会展示给你的既有代码路径。问一问:过程从哪里开始,接下来发生什么,信息去了哪里,还有哪些系统会碰到它。一张完整旅程的地图,比一堆变更行更容易用来推理。

3. 找回代码无法告诉你的原因。 孤立看起来不必要地复杂的设计选择,背后通常埋着一次事故——一次曾经发生过的失败的修复。问为什么:为什么要把操作写入日志而不是立即执行,为什么要重试三次而不是一次,为什么要校验一个看起来明显没问题的字段。代码告诉你系统做什么;历史解释为什么有人这样构建它——在你知道这些之前,你无法判断移除一道防护是在简化,还是一场即将发生的回归。

对我而言,这意味着要弄懂 Cora 为什么在行动之前先把每一个预期动作写入永久日志。曾经有一次数据库变更混淆了记录 ID 与动作的对应关系,一夜之间破坏了几十万条记录。因为“预期动作”的日志还在,我们可以重放它,用两天时间恢复,而不是从零重建。

4. 让模型考你,但别把考试变成合并的门槛。 这个做法来自 Thariq Shihipar。在一次长时间会话后,请他写出解释,并就任何变更给你一份小测验。Thariq 只有在满分之后才会合并。我让测试决定工作能否合并;小测验找出我还需要学什么。如果我答错一题,我会把那个错误留在清单上。

“但我只在乎它能用”

我听到最多的反对意见,某种版本是“我只在乎它能用”——这也是我最没有资格反驳的一种,因为作为总经理(general manager),在乎结果而不是过程本来就是我的职责。我的版本更具体:产品判断来自观察用户,而不是读 diff。我最出色的一些决定,来自看着某个人使用 Cora,并感觉到哪里不对。读源代码不会让我得到那些判断。

但在一个 AI 产品上,看起来是品味问题的地方,实际上是伪装成品味问题的机制问题。决定 Cora 该怎样处理一封 40 条消息的线程,意味着决定模型获得多少上下文、客户等多久、请求花多少钱。如果我不理解这些取舍,我就无法判断一个提议的限制是真正的约束,还是只是因为第一版碰巧能跑。

技术理解不会取代品味,但它给了我所需的材料,让我能把品味应用到那些否则我根本无法想象或评估的产品上。

把灯打开

曾经像是我的优势的工具,正在变得越来越容易被复制。领域知识,以及知道该把机器指向哪里的判断力,则不是。有经验的人在这里最危险——初级工程师会不断遇到不熟悉的东西,但如果你已经知道很多,“我知道了”随时都可以当作借口。

所以,逼自己一下。挑一件你多年来一直在绕开的任务,然后为它定义一个可衡量的版本。把“把后端做得更好”换成“找出这个请求的时间花在哪里,并砍掉 50 毫秒”。把“理解前端”换成“解释为什么这个组件渲染了三次”。具体性让工作成为可能,而你感到的阻力本身就是有用信息。在亲自实践的过程中,我理解了以下三件事:

想学,没有替代品。 哪怕是严格的关卡,也可能输给一个疲惫的周五下午;/ce-explain 从一开始就不是关卡。它不能让我想学——它只是拿掉了“我没有时间自己写这课”的借口。

知道怎么用工具,不等于知道那份工作。 学习如何使用 AI 值得做,但学习 AI 正在替你做的“那份工作”是另一项任务,也更容易被搁置。人们很容易把全部注意力都放在模型周围那套“外部装置”上——路由、提示词——却忘了重点原本是产品。

理解不会在赚到之后自动留下来。 我现在几乎每天都这么做:一个概念,往舒适区外再推一点。这让工作不再那么铺天盖地,也更有趣。AI 可以让我们更像人,但前提是我们不断选择留在工作之中。


作者简介:Kieran Klaassen 是 Every 邮件产品 Cora 的总经理。可在 X(@kieranklaassen)和 LinkedIn 关注他。

核心启示:在智能体工作流里,人贡献的不是代码,而是判断力;如果判断力没有像代码库一样持续复利,系统会越来越强,而人的判断会越来越弱。

To Read—Or Not to Read the Code? 的发芽报告

材料核心

Kieran Klaassen 在 AI 代理时代发现自己的产出在增长、判断力却在倒退。他的解法是重新“读代码”——不是为了审查,而是为了学习,在自动化面前有意识地维护自己的“辨别力”。这篇个人记录同时触及一个更大的问题:当代理替你完成越来越多的认知工作,谁在替你维护那颗做判断的大脑?


发芽 01:暗工厂的灯,从来不只在车间里

种子

Klaassen 用“暗工厂”做比喻:自动化的理想状态是灯熄灭、无人值守、机器自行运转。但他认为危险在于,当你自动化自己的工作时,可能连自己脑子里的灯也一起关了。这个比喻在工业生产中有真实的对应物——而历史已经反复证明过,那些能在暗中运行的系统,最怕的不是机器故障,而是人不再理解机器。

故事

制造业真正实现过“暗工厂”。1980 年代起,日本 FANUC 在富士山脚的工厂里,用机器人制造机器人,生产线可以在无人状态下连续运行数周。但那个年代的人很清楚:灯可以关,维修手册不能丢。真正让“暗工厂”变成灾难隐喻的,是另一类系统——自动化程度同样极高,却在关键时刻暴露了人的认知空洞。

2009 年 6 月 1 日,法航 447 航班从里约热内卢飞往巴黎,A330 的空速管结冰,自动驾驶断开。飞机失速,但副驾驶在失速警告连续鸣响时持续拉杆抬头,始终没有识别出失速状态,也没能执行标准的失速改出程序。几分钟后,228 人坠入大西洋。调查委员会的结论之一,是飞行员在依赖自动驾驶的飞行模式下,丧失了手动飞行中本应高度熟练的失速判断力。

安全研究者把这称为“自动化的讽刺”(Bainbridge, 1983):系统越可靠,人的干预需求越少;但那些需要干预的时刻往往最致命,而那时恰好是人最生疏的时刻。Klaassen 文章里引用的 Margaret Mitchell 等人的论文、以及他追查 Cora 删除邮件的 bug,本质上是同一个结构:自动化系统能运行几个月不犯错,直到一个边界情况出现——客户编辑并发送了一封尚未提交的草稿——旧 bug 浮出水面。这时需要的不是“读每一行代码”,而是对整个系统的抽象地图足够清晰,才能判断两个“听起来都对”的修复方案其实都错。

Aha 瞬间

自动化不是替你把判断力收起来,而是替你把判断力保管在仓库里——而当你真正需要接管的那一刻,正是你最不擅长接管的那一刻。


发芽 02:读代码不是“读”,是“在你不懂的地方加杠杆”

种子

Klaassen 区分了两种读代码:读代码来验证,和读代码来学习。前一种他用代理替代了,后一种他重新捡起来了。但真正值得追问的是:为什么“读代码”这个行为本身,在某些人身上能带来成长,在另一些人身上只是安慰剂?答案不是阅读量,而是阅读的方式。

故事

Anders Ericsson 在 1993 年那篇著名的论文里,研究了柏林音乐学院的小提琴学生。最优秀组的练习时间不是最长,但他们的练习方式完全不同:聚焦于自己最弱的片段,放慢速度,反复修正,寻求即时反馈。Ericsson 称之为“刻意练习”。与之相对的是“天真练习”——重复已经会的东西,让流畅感制造进步的错觉。

Klaassen 的四条方法几乎就是刻意练习在代码库上的操作化:第一条,列出你不懂的地方,当作你的 syllabus——“Notice every place you don’t and keep those gaps as your syllabus”;第三条,问“为什么”去恢复代码背后的历史——“code shows you what the system does. The history explains why someone built it that way”;第四条,让模型给你出测验,错了就留在清单上。这些做法的共同点,正是 Ericsson 强调的“刻意指向弱点、即时获得反馈”。

更关键的是,这种练习特意选择了难度。Robert Bjork 与 Elizabeth Bjork 提出过“有价值的困难”:学习过程中的适度挫败反而能增强长期记忆。Klaassen 在文章开头说他过去的几个月“大脑变得像 TikTok 信息流”——全是短促的多巴胺输出,没有留下任何东西。“Desirable difficulties”的反面就是这种流畅感:滑过去、消费完、什么都不剩。而他将一个概念“比舒适阈值再往前推一点”的方式,就是刻意给自己制造理解上的阻力。

Aha 瞬间

读代码本身不会让你变强;只有在你发现自己不懂的地方、并逼自己在那里多停留一会儿的时候,“读”才变成了“训练”。


发芽 03:“我只在乎它能不能工作”——但 taste 也是需要底座的第一性原理

种子

Klaassen 处理了最常见的反对意见:“我只关心它能不能工作。”作为产品型管理者,他承认看用户、感受体验中的不对劲(wrongness)常常比读 diff 更重要。但他的回应是:在 AI 产品上,很多看起来是品味判断的问题,骨子里是机制判断。“Technical understanding doesn’t replace taste, but gives me what I need to apply taste to products I couldn’t otherwise imagine or evaluate.”

故事

Daniel Kahneman 在《思考,快与慢》里提出过一个隐蔽的认知陷阱:我们通常基于眼前可见的信息进行判断,并将这种判断的流畅感误认为正确感。他叫它“WYSIATI”——What You See Is All There Is。

AI 生成代码时,它给我们的恰恰是“一个看起来完全合理的浮在表面的解释”。如果我们的 taste 没有机制知识的底座,那么“我觉得不对劲”就只是一种模糊的焦虑,而不是可操作的方向。Klaassen 的 Cora 删除邮件 bug 是最好的演示:两个最初的修复方案都很合理——等 30 秒再删,或跳过 Cora 自己发出的草稿。它们错在同一个地方:基于错误的心理模型。真正的异常是“客户在 Gmail 里编辑并发送了草稿”,超出了这两个方案能覆盖的信号范围。如果没有对 Gmail 事件、Cora 内部 cleanup 流程之间关系的整体理解,这两个“合理方案”就会成功合入,而同一个致命条件还会再发生。

也正因为这样,他自己的破局方式不是“更严厉的审查”,而是先建立一张可以推理的系统地图,再把防线变成一条不猜测的规则:删除前直接问 Gmail“它还是草稿吗”,如果 Gmail 不能确定,就不删。这个规则能站住,不是因为它看起来优雅,而是因为它对系统约束的建模是准确的。

Aha 瞬间

没有机制理解的 taste 只是“我感觉不对”;有机制理解的 taste 才是“我知道该查哪里”——AI 时代的产品判断力,本质上是你对底层因果链的建模能力。


你的思考空间

  • 你上一次“知道系统为什么这样做,而不是只做对了它决定的事”是什么时候?如果不查文档/不问 AI,你还能画出你手上系统的一页因果地图吗?
  • “自动化替你完成工作”和“自动化替你完成理解”之间的界限在哪里?什么时候你会主动选择不用 AI、走一遍从原始材料到结论的完整路径?
  • Klaassen 说“先定义可测量的版本”——如果你要重启自己的某一项底层技能(前端、数据库、算法直觉),你的“50 毫秒”目标是什么?
  • 如果“判断力”是随代码库一起复合增长的能力,那么当人离开一个代码库、换到新的系统时,这种成长是迁移的,还是会被重置?你如何验证自己的“判断力曲线”没有和系统的复杂度曲线分叉?