@dzhng: https://x.com/dzhng/status/2090252351533973768
摘要
这篇文章讨论了因人工审查瓶颈而产生的AI生成代码‘垃圾’问题,并指出软件工程必须演进,以系统设计为重点,而不是代码的可读性。
查看缓存全文
缓存时间: 2026/08/21 05:04
建造软件工厂(拒绝代码水文)
当今代码产出量远超我们审查代码的能力。这点无可争议。更值得思考的是,我们正明显处于劣势——现代代码库中充斥的AI生成代码混乱度已达到惊人程度,而AI编码显然不会消失。那么我们该何去何从?是全盘接受这种混乱,还是能找到鱼与熊掌兼得之道?
我认为存在一条出路。但这需要放弃大多数人尚未准备舍弃的东西。请看:
https://x.com/dzhng/status/2089763660260651318
https://x.com/dzhng/status/2089763660260651318
混乱的根源不在于模型质量
在GPT-4和Sonnet-3时代或许如此,但如今情况已不同。最先进模型在代码生成方面已基本成熟(注意我在此明确区分了“编码”与“软件工程”,后文详述)。当生成过程不受限制而验证环节受制于人类阅读瓶颈时,代码混乱便应运而生。
想想这个循环:代码生成速度每季度都在加快,而审查环节仍保持固定的人工速率。当供给远超审核能力时,审核就不再是过滤器而沦为形式主义。你快速浏览,你点击批准。“LGTM”成为默认选项,代码质量便滑向仅能通过扫视检查的水平。今天在大型团队工作过的人都见过这种现象。
若目标仍是逐行阅读代码,我们将受制于自身的审查能力,质量最终趋向于零。 这种退化已有其名,我们都在使用它。
因此两种显而易见的策略都是失败者:接受混乱意味着承认质量退化;放慢生成速度匹配阅读效率则完全放弃了AI带来的优势。唯一可行之道是消除人类阅读成为瓶颈的现状。
情况更糟:代码将变得不可读
目前我们正处于尴尬的过渡期。AI仍在生成人类可读的代码:TypeScript、Python等具有明确命名的语言——这主要是因为它从我们这里学习,且我们仍参与流程。
我认为这种状态不会持久。我预见代码可读性将随时间推移不断降低。或许它将用Claude语言编写;或许我们会发明专为AI设计的新语言——更节省token、为非人类读者优化;甚至可能直接生成机器码。
应对代码过多无法阅读的标准方案是引入更多AI辅助阅读。但这些审查者被锚定在代码产物上,而代码产物正变得不透明。每一次代码生成技术的进步都会削弱它们的审查相关性和实用性。
我对软件工程依然极度乐观
尽管已深度拥抱AI,我仍认为只要计算机存在,软件工程师就会存在。
原因在于这份工作的本质从来不是编写代码。工程是解决问题。这才是程序员与工程师的本质区别——程序员的产出是代码,工程师的产出是被解决的问题,而代码只是我们解决问题时使用的介质。
如果认同这点,那么“AI现在编写代码”就不是对这个职业的攻击,而是介质的变革。软件工程的未来在于构建与AI协同解决商业问题的系统——明确规范内容、分配方式、验证机制以及信任建立标准。
这个系统如今就是交付物。由此引出真正的问题:整个软件开发生命周期(SDLC)都基于你能阅读代码这一假设
我们所有流程都建立在此假设之上:拉取请求、代码审查、批准机制、代码检查与格式化工具、风格指南、制表符与空格之争。所有这些都是围绕人类能够打开文件并理解其功能而搭建的脚手架。
若该假设崩塌,修补流程将无济于事。我们需要全新的流程。
你早已在发布未读过的代码
审视你自己的技术栈即可。
任选一个现代应用,统计团队成员实际阅读过的发布代码占比,结果接近零。这种情况已持续至少十年。你的依赖库、它们的依赖库、其下的多层包——无人阅读,也无人会阅读,但我们照常发布。黑盒模型并非可怕的未来,而是当前生产环境中运行的所有技术栈的普遍真相。
组织层面亦然。工程副总裁对组织发布的所有内容负责。开发者向团队主管汇报,主管再向上汇报,他们可能多年不读一行代码。责任从未真正要求阅读——它要求确保系统结构能暴露问题。
我们早已知道如何为未读过的代码负责。数十年来,我们在技术和组织层面一直在这样做。唯一真正的新情况是:这现在波及到第一方代码——那些我们曾亲手编写、自认为可控,因而自以为理解的代码部分。
那么正确的方法是什么?
将代码库视为黑盒
我的思考方式是:不再将其视为代码审查问题,而是可解释性问题。
你将代码库组织成高度领域化的模块,明确定义输入输出。为每个模块添加传感器,运行函数,检查输出。通过持续质询系统——随每个新用户路径、每个边界情况、每个真实用户实际行为——逐步建立对系统的信任。
你永远不读实现代码,也不需要读。你需要知道的是:这个模块在给定这些输入时产生这些输出,并在周围环境变化时保持此行为。
实现这点的关键是接缝设计。大型单体应用(如典型SaaS产品)过于复杂,无法高效质询——输入组合过多,且许多用户路径缺乏明确的“正确”定义边界。具有明确输入输出的领域化模块,能将不可读系统转变为可检测系统。接口成为审查表面。
但采用黑盒模式只有在人类可读层向上迁移而非消失时才可行。否则我们只是在发布加密后的意图。具体而言,无论代码编译成何种形式,以下产物必须保持可读性:
- 不变式:关于该模块必须始终为真的条件,以可验证形式表述
- 运行轨迹:真实运行时在接缝处发生的情况,人类可跟随的形式
- 攻击面:该模块暴露的接口及允许接触的资源
- 决策记录:规范未明确时所做的所有选择——这是本文重点讨论部分
有人称其为规范文档,但我视之为活文档而非传统规范,因为它们记录了实施过程中大量架构决策。为避免术语争论,我们暂用中性词“产物”。
过去几个月,通过这种方式构建@duetchat及其他项目,我逐渐形成了一套经得起检验的流程。下文将详细介绍该流程。
行为告诉你“做什么”,但不解释“为什么”
传感器和不变式能证明模块按声明运行,但无法揭示代理暗中选择了乐观并发机制、发明了未指定的重试策略,或决定两个功能共享同一张表。这些不是缺陷——测试通过、输出正确、传感器显示正常。它们是决策,三个月后当你需要修改时,这些决策就会反咬你一口。
因此每当运行编码代理时,我会通过技能提示明确要求它提供决策账本——记录规范未明确时所做的每个决定,按置信度从低到高排列。一个为期两天的任务会生成数万行我永远不会审计的代码,但可能包含三十个真正决定系统正确性的决策。我阅读这三十个决策,对其中四个提出异议。
顺便说明,这并非全新理念。它正是优秀代码审查本来的作用。当资深工程师审查初级工程师的拉取请求时,有价值的部分从来不是逐行纠结细节——而是发现错误的抽象选择、遗漏的场景,或解决了与需求不同的问题。审查决策而非代码,并非我们当前工作的降级,而是剥离了偶然因素后我们一直想达成的目标。
关键实现细节:确保审计者与实施者分离(通过独立子代理),因为模型自我审查会受自身意图影响而合理化。审计永不应阻塞流程或修改代码,因为它一旦能修复问题,就会开始优化“清洁报告”而非真实记录。
总结:输入意图,输出行为,实现过程可完全不可读。 即使代码变成Claude语言、AI原生语言或原始机器码,这两个表面都能存活。它们都不是最终产物。
这也解答了原帖中“何必坚持TypeScript”的问题。最终你不必坚持,但可解释性不会丢失——可解释性从来不存在于语法中,而是存在于意图里,源代码只是我们最后选择记录意图的地方。将其上移一层,编译目标就不再重要。
是的,这本质上是将规范“编译”为代码。常见反对意见是:编译器是确定性的,而AI是概率性的。这很公平——但放大视角会发现实际被替代的并非编译器,而是曾经编写代码的人,而他们从来不是确定性的。意图与产物间始终存在概率性步骤,我们称之为程序员,并围绕其不可靠性构建了审查、测试和分阶段发布。这些工具不会因为概率步骤速度提升千倍而失效。
正确运用后,争论该用哪种语言或框架,其重要性约等于争论制表符与空格哪个更好。
真正困难在于模块切分
这不是简单地将目标分解为任务。你需要可独立验证的模块:能独立构建、独立监控、可能独立出错的组件。这些模块正是你附加传感器的位置,也是防止决策12通过30无声毒害决策13的边界。一套规范,两个表面。
更困难的问题在上一层:如何识别模块边界。分解目标前需先了解其形态,而通常无人知晓——无论是你还是代理。这正是长时间任务失败的根本原因,不是难题,而是未知盲区。
我将其视为战争迷雾。先侦察再规划:逐象限扫描目标,厘清已知、未知和盲区,返回渲染后的选项和决策表供响应,而非要求凭空想象。将探测出的区域划分为可独立攻占的领地。若某领地暗藏更多未知地图,重新切分并再次侦察。
所有扫描都无需完美,但必须诚实。每次迭代都更接近正确,长时间运行中“更接近正确”的累积效应就是任务完成的方法。
一个无人值守、追求单一目标的任务运行1天16小时——切分、构建、验证、重切分。我审查的是决策账本,而非代码差异。
一个无人值守、追求单一目标的任务运行1天16小时——切分、构建、验证、重切分。我审查的是决策账本,而非代码差异。
端到端的完整循环
绘制迷雾地图:逐象限梳理构想,直至明确构建内容。
编译规范:撰写规范文档。主要是转录和对抗性规划,因为决策已在上游成本较低时完成。
构建系统:将工具置于循环模式,让规范驱动构建。按模块触发审查;若构建证明计划过时,计划自动重切分。
审查决策:阅读决策账本,从置信度最低处开始,提出异议,等待重新审计。
我的实际主张
总结核心观点:阅读代码并未消亡,在某些场景下仍需阅读代码(尽管这类场景正减少),且你必须能理解AI代表你所做的任何代码和架构决策。AI编码也不是懒惰和忽视工程原则的借口——事实上此时原则比以往更重要。
更精确的主张是:若我们继续将产物的人类阅读作为验证环节,代码混乱将不可避免,任何审查(无论人工或AI)都无法解决。将问题视为可解释性问题才是解决之道。
对我来说可行的方案有两个:具有清晰接缝和传感器的黑盒系统,以及结构化的决策记录(含决策内容与置信度)。
这就是我心中软件工厂的定义。不是编码代理,而是将意图和行为作为受检产物,代码只是最终副产品的生产线。
我用于运营自己软件工厂的技能库在此(仍在开发中):
https://github.com/dzhng/skills
仍想了解其他tokenmaxxers的看法。我仍在与所有人一同探索中。
相似文章
如何避免AI代码质量下降
本期通讯文章讨论了AI生成代码速度超过人工代码审查速度所导致的“AI代码质量下降”问题,并提供了平衡速度与质量的策略。
@saranormous: https://x.com/saranormous/status/2064510215056400652
尽管以Devin为代表的AI编程助手取得了快速进展,显著提升了代码编写和交付的速度,但本文认为,软件工程中最有价值的部分仍难以通过基准测试衡量,并且需要人类的判断和组织协调,这些是无法轻易自动化的。
@dzhng: 喜欢这个框架。软件工厂不应该要求人类审查每一行代码,但每一个*决策*都应该…
开发者 dzhng 分享了一个 GitHub 仓库,其中包含可组合的 AI 代理技能,用于构建软件工厂,实现自主目标驱动代码生成,并在决策点进行人工审查。
@SaitoWu: https://x.com/SaitoWu/status/2053101671035851216
The article summarizes a talk by Matt Pocock criticizing 'specs-to-code' approaches, arguing that solid software engineering fundamentals like TDD and modular design are more critical than ever for effectively using AI coding assistants like Claude Code.
“AI slop”辩论将三个不同的问题混为一谈:作者归属、生产力和工程质量
文章认为,“AI slop”的争论混淆了作者归属、生产力和工程质量,并提议将生成式编码系统视为工程控制回路中的高吞吐量、易出错的生产者,将稀缺技能转向规范制定、验证和问责。