我们来不及验证 AI 生成的代码了

AI编码革命有一个肮脏的秘密:大多数有经验的开发者仍然不太信任AI为我们写的代码。

如果坦白说,这其实不是一个特别保守的秘密。感觉每天都有新的令人惊叹的"我没有任何开发经验但我刚刚用vibe编程做出了这个惊人的应用"的文章。我理解——这类文章能获得如此多的互动,因为每个人都在密切关注AI越来越擅长写代码的戏剧性发展。我们有几十年的影视作品,从《战争游戏》到《黑客》到《机器人先生》,把开发者描绘成用计算机做着神秘但不可思议的事情的隐世天才。我们已经把自己编码到灭绝这个想法对人们来说很迷人。

这种流行文化现象的另一面是,当agentic工程出问题导致的问题(比如同样受欢迎的"我信任了一个AI代理然后它删除了我整个生产数据库"的文章)时,每个人似乎都发现了。不幸的是,这种新出现的套路更接近现实。大多数从事agentic工程的人都见过自己AI生成的代码脱轨。这就是为什么我构建并维护了Quality Playbook,一个开源的AI技能,使用超过五十年的质量工程技术来帮助使用任何语言的开发者验证他们AI生成代码的质量。我像所有人一样惊讶地发现它确实有效。

我经常谈到在使用AI写代码时我们需要一种"信任但验证"的心态。过去,我主要关注"信任"方面,寻找帮助开发者更舒适地采用AI编码工具并将其用于生产工作的方法。但我越来越相信,AI驱动开发的最大问题是我们没有可靠的方法大规模验证agentic工程代码的质量。AI写代码的速度超过了我们验证它的速度,这是AI目前最大的问题之一。

1、一个虚假的选择

在我第一次真正体验到在专业环境中使用AI进行开发之后,感觉好像我被要求做出一个关键选择:要么我必须把我所有的思考外包给AI,然后信任它构建我需要的任何代码,要么我必须逐行审查它生成的每一个文件。

我交谈过的许多非常优秀、非常有经验的高级工程师也有同样的感觉。少数有经验的开发者完全拥抱vibe编程,基本上让AI去做它需要做的事情,依靠单元测试和可靠的解耦架构(也许还有一点运气)来确保一切顺利。但更常见的是,我交谈过的高级、有经验的工程师——那些开发很长时间的人——走向了另一个方向。当我问他们是否每天都在使用AI时,他们几乎总是会说类似这样的话:"是的,我用AI来写单元测试和代码审查。"这几乎总是表明他们不信任AI来构建应用程序核心的真正重要的代码。他们只在即使出问题也不会导致生产bug的事情上使用AI。

我认为最近Ars Technica一篇优秀文章"认知投降"导致AI用户放弃逻辑思维中的这段摘录总结了许多有经验的开发者对使用AI的感受:

当涉及大型语言模型驱动的工具时,通常有两大类用户。一方面是那些将AI视为一个强大但有时有缺陷的服务的人,需要仔细的人工监督和审查来检测响应中的推理或事实错误。另一方面是那些经常将他们的批判性思维外包给他们视为全知机器的人。

我同意这是处理AI的两种选择。但我同时也认为这是一个虚假的选择。正如文章引用的研究所说的"认知投降"不是一个好结果。但逐行审查AI写的每一行代码也不是,因为那太费精力了,我们还不如自己写。(我几乎能听到你们中的一些人在问,"那有什么不好?")

这个虚假的选择正是今天推动许多非常优秀、非常有经验的高级工程师远离AI驱动开发的真正原因。我们看到这两个选项,它们都糟透了。这就是为什么我要写这篇文章(以及本系列接下来的几篇)来讨论质量问题。

2、关于AI编码工具的一些令人震惊的数字

Quality Playbook是一个为GitHub Copilot、Cursor、Claude Code和Windsurf等AI编码工具提供的开源技能。你把它指向一个代码库,它就会为该项目生成完整的质量工程基础设施:追溯到需求的测试计划、代码审查协议、集成测试等等。更重要的是,它带回了整个行业几十年前放弃的质量工程实践,使用AI来做过去需要一个专门团队才能完成的大量质量相关工作。

我构建Quality Playbook是AI驱动开发和agentic工程实验的一部分,构建了一个名为Octobatch的开源项目,并在这个持续的Radar系列中记录了这个过程。这个playbook直接从那个实验中诞生。它背后的理念有超过五十年的历史,而且它们确实有效。

在此过程中,我遇到了一个令人震惊的统计数据。

我们已经知道如今许多(大多数?)开发者使用GitHub Copilot、Claude Code、Gemini、ChatGPT和Cursor等AI编码工具来编写生产代码。但我们信任这些工具生成的代码吗?"对系统的信任已暴跌至仅33%,比2023年的70%以上急剧下降。"

这句话来自我在为本文做研究时生成的Gemini Deep Research报告。70%降到33%——听起来像是大规模崩溃,对吧?

问题是,当我检查Gemini引用的来源时,事实远没有那么清晰。"2023年的70%以上"这个数字来自Stack Overflow调查,衡量的是开发者对AI工具的看法有多正面。"33%"这个数字来自Qodo调查,问的是开发者是否信任AI生成代码的准确性。Gemini抓取了两个数字,剥离了上下文,并把它们拼接成一个下降的叙事。没有一项研究曾经测量过信任度从70%以上下降到33%。这意味着我们有一个苹果和橘子的比较,它在技术上甚至可能是准确的(也许?),但它并不像看起来那样是一个引人注目的头条。

那么我为什么要告诉你这些?

因为那个"令人震惊的"统计数据有两个重要的教训。第一个是整体思路至少对我来说是真实的。几乎我们所有人都有过用AI生成代码快于我们验证代码速度的经历,我们在完全审查之前就发布了功能。

第二个是,当Gemini创建报告时,AI从真实但不相关的数据点中编造了最令人警觉的故事版本。如果我不检查来源就直接引用它,它很可能被发布,你甚至可能相信它。这具有讽刺意义的自我指涉,因为它正是该调查 supposed to 测量的信任问题。AI产生了看起来权威、感觉正确但在只有仔细验证才能发现的方式上的错误的东西。如果你想理解为什么超过70%的开发者不完全信任AI生成的代码,你刚刚就看到了。

许多人不信任AI生成选择的另一个原因是,AI生成代码的速度和我们验证代码是否真正实现了我们意图的能力之间存在日益扩大的差距。对这种验证差距的通常回应是采用更好的测试工具。有很多这样的工具:测试桩生成器、diff审查器、规格优先框架。它们很有用,解决了真正的问题。但它们通常有一个盲点:它们处理代码做什么,而不是代码应该做什么。幸运的是,意图就在那里:在规格、模式、防御性代码、AI关于项目的聊天历史中,甚至在变量名和文件名中。我们只需要一种使用它的方法。

AI驱动开发需要自己的质量实践,而我们所需要的学科已经存在。它只是(不公平地)被认为太昂贵而无法使用……直到AI让它变得便宜。

3、(重新)引入质量工程

知道代码能工作和知道代码做了它应该做的事情是有区别的。这是"这个函数返回的值正确吗?"和"这个系统实现了它的目的吗?"之间的区别——而事实证明,这是软件工程中最古老的问题之一。事实上,正如我在之前的一篇Radar文章提示工程就是需求工程中所谈到的,它是原始"软件危机"的根源。

软件危机是20世纪60年代我们行业的人们用来描述全球大型软件项目经常延期交付、超出预算、交付的软件不做它应该做的事情的术语。在1968年的NATO软件工程会议上——引入"软件工程"一词的会议——行业的一些顶级专家谈论了危机是如何由开发者和他们的利益相关者在理解他们解决的问题、清晰地传达这些需求以及确保他们交付的系统真正满足用户需求方面遇到困难所引起的。近二十年后,Fred Brooks在他开创性的文章没有银弹中提出了同样的论点:没有任何工具能够自己消除理解需要构建什么和清晰传达该意图的固有困难。现在我们像和队友交谈一样与我们的AI开发工具交谈,我们比以往任何时候都更容易受到沟通和共同理解这个潜在问题的影响。

行业对软件危机回应的一个重要部分是质量工程,一门专门为弥合意图和实现之间的差距而建立的学科,通过预先定义"正确"的含义、将测试追溯到需求,并验证交付的系统确实做了它应该做的事情。多年来,软件工程团队在所有项目中包含质量工程阶段是标准做法。但如今很少有团队做传统的质量工程。理解为什么它被我们中的许多人抛弃,更重要的是,它现在能为我们做什么,可以给当今的agentic工程和AI驱动开发带来巨大的改变。

从20世纪50年代开始,三位思想家建立了制造业用来变得更加可靠的智力基础。

  • W. Edwards Deming认为质量是内建于流程中的,而不是事后检验的。他教会我们,你无法通过测试来获得好产品;你必须设计产生它的系统。
  • Joseph Juran将质量定义为适用性:不仅仅是"它能工作吗?"而是"在真实条件下,对于实际使用它的人来说,它是否做了它应该做的事情?"
  • Philip Crosby提出了商业论证:质量是免费的,因为内建质量的成本远低于事后发现和修复缺陷的成本。到我在20世纪90年代加入我的第一个专业软件开发团队时,这些理念已经成为我们行业的标准做法。

这些理念彻底改变了软件质量,将它们付诸实践的人被称为质量工程师。他们构建追溯到需求的测试计划,针对规格运行功能测试,并维护定义系统中每个部分"正确"含义的活文档。

那么为什么所有这些从大多数软件团队中消失了?(它仍然在航空航天、医疗器械和汽车等受监管的行业中存在,在这些行业中可追溯性是法律要求的,以及整个行业中少数勇敢的坚持者。)这不是因为它不起作用。质量工程被削减是因为它被认为太昂贵。Crosby说质量是免费的是对的:内建质量的成本远远超过了你从不在以后发现和修复缺陷中获得的节省。但成本在项目开始时出现,而节省在项目结束时出现。在实践中,这意味着当团队错过了截止日期、经理生气并开始寻找可以削减的东西时,测试和QA活动很容易成为目标,因为软件看起来已经完成了。

在被认为昂贵的成本之上,质量工程需要专业人员。构建好的需求、设计测试计划以及规划和运行功能和回归测试是真正的技术技能,大多数团队根本没有能够做这些工作的人(或者更具体地说,没有这些人的预算)。

质量工程可能随着时间的推移从我们的项目和团队中消失了,但行业并没有放弃它的许多最佳理念。开发者没有什么是不足智多谋的,我们构建了自己的质量实践——其中最流行的三个是测试驱动开发、行为驱动开发和敏捷风格迭代——它们在各自的领域确实做得很好。TDD通过让你在实现之前编写测试来保持代码的诚实。BDD专门设计用来以一种开发者、测试者和利益相关者都能阅读的形式捕获需求(虽然在实践中,大多数团队剥离了利益相关者的参与,它退化为另一种风格的集成测试)。敏捷迭代收紧了反馈循环,让你更早地发现问题。

这些较新的质量实践是实用的、面向开发者的,并且在短期内采用它们比传统质量工程成本更低,因为它们存在于开发周期内。这些实践的好处是开发团队通常可以自己实施,而不需要请求许可或需要专家。然而,代价是这些实践的范围有限。它们验证你正在编写的代码正确工作,但它们不会退后一步问整个系统是否实现了它的原始意图。另一方面,质量工程在开发周期开始之前就确立了系统的意图,并随着项目的进展保持更新和反馈给团队。这是沿途丢失的巨大一块拼图。

那些高度有效的质量工程实践被从大多数软件工程团队中削减是因为它们被认为昂贵,而不是因为它们是错误的。当你做AI驱动开发时,你实际上遇到的是质量工程被设计来解决的同一个问题。你有一个"团队"——你的AI编码工具——你需要一个结构化的流程来确保那个团队正在构建你真正想要的东西。质量工程非常适合AI驱动开发,因为它是专门设计来弥合你要求的东西和构建出来的东西之间差距的学科。

没有人预料到的是,AI会在短期内让它变得足够便宜,使质量工程回到我们的项目中。

4、介绍Quality Playbook

我早就怀疑质量工程将是AI驱动开发(AIDD)的完美搭配,我终于有机会测试这个假设。作为我AIDD和agentic工程实验的一部分(我一直在The Accidental Orchestrator和本系列的其余部分中记录),我构建了 Quality Playbook,一个为Cursor、GitHub Copilot和Claude Code等AI工具提供的技能,让你能够将这些高度有效的质量实践带到任何项目中,使用AI来做过去需要一个专门质量工程团队才能完成的工作。像其他AI技能和代理一样,它是一个结构化文档,插入AI编码代理并教它一个特定的能力。你把它指向一个代码库,AI探索代码,阅读它能找到的任何规格和文档,并为该项目生成完整的质量基础设施。Quality Playbook现在是awesome-copilot的一部分,这是一个社区贡献的代理集合(我也向Anthropic的Claude Code技能库提交了一个拉取请求来添加它)。

"质量基础设施"实际上意味着什么?想想如果你雇佣了一个质量工程团队他们会构建什么。一个好的质量工程师会首先为你的项目定义"正确"的含义:系统应该做什么,基于你的需求、你的领域、你的用户实际需要什么。从这里开始,他们会编写追溯到这些需求的测试,构建一个检查代码是否实现了它应该实现的东西的代码审查流程,设计验证整个系统协同工作的集成测试,并建立一个审计流程,让独立审查者对照原始意图检查代码。

这就是playbook生成的内容。使用AI工具的开发者一直在重新发现需求的价值,规格驱动开发(SDD)已经变得非常流行。你不需要实践严格的规格驱动开发来使用它。playbook从任何可用的产物中推断你项目的意图:聊天日志、模式、README文件、代码注释,甚至防御性代码模式。如果你有正式的规格,很好;如果没有,AI从它能找到的证据中拼凑出"正确"的含义。

一旦playbook确定了代码的意图,它就为项目创建质量基础设施。具体来说,它生成十个交付物:

  • 探索和需求引出(EXPLORATION.md): 在playbook写任何东西之前,它花费整个阶段阅读代码、文档、规格和模式,并编写一个结构化的探索文档,映射项目的架构和领域。AI生成质量工作最常见的失败模式是产生可以应用于任何项目的通用内容。探索阶段迫使AI将所有内容扎根于这个特定的代码库中,并作为审计跟踪:如果需求最终是错误的,你可以将问题追溯到探索发现或遗漏的内容。
  • 可测试需求(REQUIREMENTS.md): 最重要的交付物。在探索的基础上,一个五阶段管道从代码、文档、AI聊天、消息、支持工单以及你可以给它的任何其他项目产物中提取项目的实际意图。结果是一个规范文档,新的团队成员或AI代理可以从头到尾阅读并理解该软件。每个需求都标记有一个权威层级,并链接到用例,用例成为将需求连接到集成测试再到bug报告的纽带。
  • 质量宪法(QUALITY.md): 为你的特定项目定义"正确"的含义,基于你的实际领域。每个标准都有一个解释其为什么重要的理由,因为没有理由,未来的AI会话会把标准谈下来。
  • 规格追溯的功能测试: 从需求而非源代码生成的测试。这个区别很重要:从源代码生成的测试验证代码做了代码做的事,而从规格追溯的测试验证代码做了你意图做的事。
  • 三遍代码审查协议及bug报告和回归测试: 三次强制审查,每次使用不同的视角:带有反幻觉护栏的结构性审查、需求验证(在这里你捕捉代码没做它应该做的事)和跨需求一致性检查。每个确认的bug都有一个回归测试和一个补丁文件。
  • 合并的bug报告(BUGS.md): 每个确认的bug都有完整的复现细节、根据现实世界影响校准的严重性,以及引用代码违反的特定文档的规格依据。维护者对"你的代码违反了你自己的规格第X.Y节"的反应与"这看起来可能是一个bug"不同。
  • TDD红绿验证: 对于每个确认的bug,一个回归测试针对未修补的代码运行(必须失败),然后应用修复并重新运行测试(必须通过)。当你告诉维护者"这是一个在你当前代码上失败、通过这个一行修复就能通过的测试"时,这与bug报告有着本质的区别。
  • 集成测试协议: 一个结构化的测试矩阵,AI代理可以自主捡起和执行,而不需要询问澄清问题。每个测试指定确切的命令、它证明了什么以及具体的通过/失败标准。字段名和类型从实际源文件中读取,而不是从记忆中回忆,作为一种反幻觉机制。
  • 三模型规格审计委员会: 三个独立的AI模型根据需求审计代码库。分流使用置信度加权,而不是多数投票:三个模型的发现是近确定的,两个是高置信度的,只有一个模型的发现会获得验证探测而不是被驳回。最有价值的发现往往只有一个模型捕捉到。
  • AGENTS.md引导文件: 一个未来的AI会话首先读取的上下文文件,以便它们继承完整的质量基础设施。没有它,每个新会话都从零开始。有了它,质量宪法、需求和审查协议在每次接触代码库的会话中自动延续。

5、第三种选择

我在本文开头谈到了一个虚假的选择:要么我们将判断力投降给AI,要么我们陷入审查它写的每一行代码。现实要微妙得多,而且在我看来,如果我们有一种可靠的方法来验证我们与AI合作构建的代码确实实现了我们的意图,那就有趣得多。这不巧合地是软件工程中最古老的问题之一,也不令人惊讶的是AI可以帮助我们解决这个问题。

Quality Playbook严重依赖经典的质量工程技术来进行验证。这些技术非常有效,这给了我们更细致的选择:使用AI帮助我们编写代码,然后使用它来帮助我们信任它构建的东西。

这不是一个噱头或悖论。它有效是因为验证恰恰是AI擅长的那种结构化的、规格驱动的工作。编写追溯到需求的测试、对照意图审查代码、检查系统在真实条件下是否做了它应该做的事情。这些是质量工程师过去在整个行业中做的事情(在高度监管的行业中仍然如此)。这些也是AI可以做得好的事情,只要我们告诉它"正确"意味着什么。

我在本文开头谈到的那位有经验的工程师——那些只把AI用于单元测试和代码审查的人——他们谨慎行事并没有错。他们说我们不能只信任AI输出的任何东西是对的。但将AI限制在我们项目中只做"安全"的部分阻碍了我们利用如此重要的一组工具。走出这个困境的方法是构建使其余部分也值得信任的基础设施。质量工程给了我们那个基础设施,而AI让它变得足够便宜,可以每天在我们所有的项目上实际使用。


原文链接: AI Is Writing Our Code Faster Than We Can Verify It

汇智网翻译整理,转载请标明出处