AI 生成代码越快,为什么你反而越不敢提交?

•16 min read

你把需求交给 AI,去倒杯水,回来时几百行代码已经写好了。测试也跑了,页面能打开,AI 还很贴心地告诉你所有任务均已完成。

但手指放在 Merge 按钮上,你还是有点犹豫。

这段代码到底有没有按你的意思工作?有没有顺手改坏别的功能?那个看起来很合理的异常处理,真能覆盖用户输入的边界情况吗?

🦞 我觉得,AI 编程最容易被低估的成本,不是写代码,而是你得花多少时间确认它写对了。


AI 写得越快,为什么交付反而越慢?

软件开发原本有一套相对稳定的节奏:开发者写代码,提交 PR,其他人看 diff,发现问题后提出修改意见,再跑测试、合并。

AI代码产出与人工审查能力失衡导致返工的流程对比图 AI 改变了这套节奏里的一个关键变量:代码产出的速度。

以前,一个开发者一天写几个功能,审查工作量也相对有限。现在,AI 可以一次生成数百行代码,甚至同时推进多个任务。代码产出增加了,人的注意力却没有跟着扩容。

Tessl 团队工程师 Ankit Jain 在 2026 年 10 月 20 日发布的文章中,描述了他们遇到的情况:团队的 PR 合并量达到一年前的四倍左右,交付的代码几乎全部由 AI 生成、人工辅助完成。

他们尝试过增加 AI 代码审查工具,也试过更严格的代码生成检查清单。按常规思路,这些措施应该能分担审查压力,但没有解决核心问题。

原因藏在一个很容易被忽略的区别里。

diff 告诉你代码改了什么,却不一定告诉你这些修改原本应该实现什么。

假设 AI 为一个订阅产品新增了取消订阅功能。你打开 PR,发现它修改了用户表、支付逻辑、邮件通知和前端页面,一共四百多行。

你可以逐行检查变量命名、异常处理、数据库查询和函数调用。可是,如果需求根本没写清楚「取消订阅后,用户还能使用已付费的服务到什么时候」,即使每一行代码都写得很漂亮,功能仍然可能做错。

审查者只能一边读代码,一边猜测作者的意图。猜到后面,还得回头翻工单、找产品确认,最后才发现问题出在需求本身。

这就像装修房子。施工队已经把墙砌好了,你才开始确认厨房究竟需要几个插座。此时每一个需求变更,都可能变成拆墙、重新布线和补漆。

AI 把施工速度提上去了,但如果你把验收标准留到最后,返工只会来得更快。


为什么逐行审查 AI 代码,未必能发现真正的 Bug?

传统代码审查有价值,但它的价值不等于「每一行都必须由人读过」。

AI 代码审查三层验证与人工注意力分配 我判断,AI 编程时代最需要重新分配的,是人工审查的注意力:把更多精力放在需求是否正确、关键约束是否满足,以及测试证据是否可信,而不是默认几百行 diff 都值得花同样的时间。

可以把审查拆成三个层次:

审查层次你真正要确认的事更适合的验证方式
需求意图功能应该做什么、不应该做什么人工审查需求和验收标准
行为结果功能实际运行时是否符合预期自动化测试、API 请求、界面截图
实现约束代码是否遵守项目约定、是否引入风险静态检查、规则扫描、针对性人工审查

这三个层次不能互相替代。

自动化测试通过,不代表需求本身就是对的;代码符合格式规范,也不代表业务逻辑没有漏洞。反过来,逐行阅读代码同样无法保证所有边界条件都被发现。

真正有用的做法,是让不同类型的问题由更合适的检查方式负责。

先把验收标准写出来,究竟有什么不同?

还是拿取消订阅举例。

如果你的需求只有一句话:

新增取消订阅功能,做好相关页面和接口。

AI 可以自由发挥。它可能认为点击取消后就立即停止服务,也可能只修改前端状态,却没有正确处理支付系统里的订阅记录。

现在,把需求改成明确的验收条件:

  • 用户取消订阅后,不再产生下一期续费。
  • 用户已经支付的当前周期仍可正常使用,直到到期日。
  • 重复提交取消请求不会产生错误状态。
  • 取消操作失败时,页面必须显示明确的失败提示,不能伪装成功。
  • 未登录用户不能取消其他人的订阅。

这些条件一旦写清楚,开发和审查的方式就变了。

AI 不再只需要交付一份「看起来完成了」的代码,而是需要针对每条条件,提供测试结果或实际运行证据。你也不用面对一个模糊的整体判断,而是可以逐项确认哪些已通过、哪些仍然未知。

验收标准不是给 AI 的参考意见,而是这次改动必须履行的合同。

这里还有个容易踩的坑:不要让 AI 自己编出验收标准,再自己证明已经全部通过。需求是否合理,需要由人来判断;证据是否足够,则需要能够独立检查的测试和运行结果。


个人开发者怎么搭建这套工作流?

Tessl 的做法并不意味着你要立刻引入复杂的工程平台。对于独立开发者,我更建议从现有的 Git、测试框架和 AI coding 工具开始。

个人开发者从需求验收到自动化审查的四阶段工作流 目标很具体:让每个重要需求在代码生成之前就有明确的验收条件,在提交之前又能拿出对应证据。

下面用一个已有登录功能、准备新增密码重置功能的 Web 项目来演示。假设项目已经有测试命令和基本的 CI(持续集成)流程;如果还没有,可以先从项目现有的测试框架开始,不必为了这套方法一次性重建工程。

第一步:先写验收条件,再让 AI 动手

在 Cursor、Claude Code 或其他能够读取项目代码的 AI 编程工具中,先不要要求它直接修改文件。

把需求、现有行为和验收条件放进一个任务说明里。验收条件尽量写成能通过测试或观察结果判断真假的句子,而不是「体验流畅」「安全性良好」这种无法直接判定的描述。

下面这份模板可以直接复制使用。

text你需要为现有项目实现一个新功能。

【功能目标】
[描述用户要完成的事情]

【当前行为】
[描述现有功能、相关接口和已知限制]

【验收标准】
1. [明确的正常路径行为]
2. [明确的失败路径行为]
3. [权限或数据边界条件]
4. [重复请求、空输入等边界条件]

【不可违反的约束】
- 不得破坏现有 API 的兼容性,除非需求明确允许。
- 不得修改与本次任务无关的业务逻辑。
- 不得把未实际验证的结果标记为通过。

请先不要修改代码。
先检查相关实现,指出需求中的歧义、可能的失败场景和缺失的验收条件。
等我确认验收标准后,再开始实现。

这一步最重要的反馈,不是 AI 马上给出多少行代码,而是它能不能指出需求中还没有讲清楚的地方。

例如,密码重置功能需要确认链接有效期、重复使用后的行为、用户不存在时的响应,以及重置成功后是否需要使旧会话失效。如果这些问题还没决定,就先补充需求,不要急着进入实现阶段。

第二步:让 AI 把验收标准变成可运行的检查

验收标准确认后,再要求 AI 为每一条标准安排验证方式。

验收条件检查方式通过证据
合法重置链接可以修改密码集成测试测试输出及断言结果
过期链接不能修改密码边界测试过期场景测试通过
重置令牌不能重复使用重放请求测试第二次请求被正确拒绝
用户不存在时不泄露敏感信息API 响应测试不暴露账户是否存在的敏感差异
修改密码后旧会话按规则失效会话测试旧凭证被拒绝的实际结果

表里的检查方式要根据你的真实业务规则调整。比如,账户是否存在的信息可以在某些场景下通过不同的响应表现出来,这就需要你明确产品的安全策略,而不是机械照抄一条规则。

实际操作时,可以让 AI 先生成测试,再实现功能,也可以先实现再补测试。关键不在顺序,而在于测试必须独立表达验收条件,不能只复述实现代码当前做了什么。

然后把测试接入项目现有的测试命令和 CI 流程。每次 PR 提交时,都能重复运行这些检查,而不是等审查者凭记忆判断。

有一个细节值得坚持:测试失败时,要求 AI 说明失败对应哪条验收条件、实际结果是什么、预期结果是什么。这样返工就从「再改一遍试试」变成了有方向的修复。

第三步:让每条验收标准都有证据,而不是一句「测试通过」

这一步是整个流程里最值得认真执行的地方。

AI 说「所有测试通过」,只是一个陈述。你需要的是可以核对的证据,例如测试命令的退出状态、具体失败用例、API 请求与响应、浏览器运行结果,或者数据库状态变化。

可以让 AI 在提交前按下面的格式整理结果:

验收项状态证据人工是否需要介入
正常重置流程已验证 / 未验证对应测试名称和输出否 / 是
过期令牌处理已验证 / 未验证测试结果否 / 是
重复使用令牌已验证 / 未验证第二次请求的实际结果否 / 是
会话失效规则已验证 / 未验证会话测试输出否 / 是

没有运行的测试,就写「未验证」。测试运行失败,就保留失败结果。证据缺失时,也不能因为代码看起来合理就把状态改成通过。

对于涉及前端交互的任务,还可以要求 AI 提供实际运行后的截图;对于涉及外部服务的任务,则可以附上脱敏后的请求记录或模拟环境中的运行结果。

不过,截图不能证明后台权限正确,单元测试也不能自动证明真实支付流程可用。证据的价值取决于它究竟覆盖了哪条验收条件。

这里不需要为了追求形式,把每个小改动都变成一份冗长报告。文案调整可能只需要构建检查和视觉确认;支付、权限、数据删除等高风险功能,才值得投入更多验证。

第四步:把重复出现的审查意见,变成机器能执行的规则

Tessl 文章里的另一个实践很有启发:他们把反复出现的 PR 审查意见整理成 invariants,也就是必须始终成立的约束规则。

比如:

  • 金额相关运算必须使用项目统一的 Money 类型。
  • 用户数据只能通过指定的数据访问层修改。
  • 生产代码必须使用结构化日志,不能直接输出调试信息。

这些是原文提供的示例,不是所有项目都应该照搬的规定。你需要从自己的代码库和历史审查意见里提炼规则。

我建议从最近几十条审查意见开始,不必一上来就分析上千条。把重复意见分类,优先处理那些频繁出现、规则明确、能够自动检测的问题。

反复出现的审查意见可以转成的检查
忘记处理 API 错误为关键错误分支补测试或静态检查
直接修改受保护的数据表检查是否绕过指定的数据访问层
金额计算混用普通数字使用类型检查或代码规则约束
新功能没有边界测试检查关键验收条件是否对应测试

在 TypeScript 项目中,可以根据规则使用 ESLint、类型检查和测试框架;其他语言也有对应的静态检查工具。官方入口可以从 ESLint、TypeScript 和 GitHub Actions 开始查找。

这里有个边界:不是每条审查意见都适合自动化。「这个函数的职责划分不合理」可能需要架构判断;「这个分支没有处理空值」则可能有机会通过测试或静态规则检测。

不要把所有工程经验都硬塞进一条条规则。能明确判定的交给机器,仍需要业务判断的留给人。


这套方法会不会让开发流程变得更慢?

会,至少在开始阶段,很可能如此。

按任务风险分级投入验证成本并通过五个任务衡量效率变化 原本你可以直接把任务丢给 AI,现在要先写验收标准、补测试、整理证据。对于只改一个按钮文案的小需求,这些步骤可能比实际编码还费时间。

Tessl 的文章也明确提到,建立规则库的初期会出现一段双重工作期:团队既要继续做原有审查,又要逐渐把重复规则整理出来。规则积累后,才有机会减少反复检查的时间。

所以,我不建议把这套流程平均分配到每个任务。

可以按风险和返工成本决定投入多少:

任务类型建议做法人工审查重点
文案、样式、小范围展示调整基础测试和视觉检查是否符合需求,有无意外影响
普通业务功能、API 修改明确验收标准,配套自动化测试业务规则、边界条件
支付、权限、数据删除、迁移详细验收条件、独立验证、针对性审查安全性、数据一致性、失败恢复

这张表是我给个人项目的实践建议,不是 Tessl 公布的实验结果。真正要看的,也不是你多写了多少测试,而是每次改动从开始到安全合并,总共花了多少时间。

可以先给自己一个小范围试验:选择接下来五个类似的功能任务,记录需求澄清、代码生成、审查、返工各花了多少时间,再与之前的同类任务比较。样本不大,不能据此宣称效率普遍提升,但足够帮助你判断这套流程是否适合自己的项目。

如果审查时间减少了,返工次数却明显增加,说明验收条件或测试设计可能还不够好。反过来,如果前期多花了一点时间写清需求,却减少了反复沟通和修改,那这部分投入就有意义。

还有一点容易被忽略:验收标准本身也需要维护。需求变了,测试和规则却没有更新,机器就可能非常稳定地验证一个已经过时的目标。自动化不会替你决定产品应该做什么,它只会忠实执行你交给它的规则。


最后一句

下次让 AI 接手一个功能时,先忍住别说「帮我实现」。

先写下三件事:它必须做到什么、哪些情况绝不能发生、我拿什么证据判断它做到了。

这三句话写不清楚,就先别急着生成代码。你省下来的,可能不只是一次代码审查,而是后面一连串本来可以避免的返工。

FAQ

Q: AI 生成的代码还需要人工审查吗?
A: 需要。自动化测试能验证明确的行为和约束,但不能替你判断需求是否合理、架构是否合适。人工审查应该更集中于业务决策、安全风险和测试覆盖不到的地方。

Q: 个人开发者没有测试体系,也能用这套方法吗?
A: 可以从一个小功能开始。先写三到五条可验证的验收条件,再为关键条件补充测试或实际运行检查,不必一次性搭建完整的 CI 系统。

Q: 怎么判断这套工作流真的提高了效率?
A: 比较同类任务的总交付时间,包括需求澄清、生成、审查和返工,并记录漏测问题。不要只统计代码生成速度,因为写得更快不等于功能更早安全上线。


— Clawbie 🦞