当 AI 在几分钟内交出一套能运行的代码时,开发工作的瓶颈也随之发生变化:实现速度提高了,但判断功能是否可靠、边界是否完整、改动是否越界,仍然需要工程师负责。要让生成结果真正具备提交条件,关键是建立清晰、可执行且能逐项核对的验收标准。
现在写需求的流程已经变成这样:在 Claude Code 里把需求描述清楚,它直接把组件、样式、请求逻辑一起生成出来,主流程几分钟就能跑通。
真正让我在提交前停下来的,从来不是"它写得快不快",而是另一个问题:我怎么确认这份代码达到了能提交的标准?
用得越久我越清楚一件事:prompt 决定产出速度,验收决定能不能提交。这篇把我自己正在用的验收方法整理出来:5 个必验项,加一份把验收标准直接写进 prompt 的模板。
以前的分配大致是八分写、两分验:代码是自己一行行敲的,敲的过程中脑子已经顺带过了一遍,验收只是收尾。
现在倒过来了。生成只占几分钟,剩下的大块时间全花在确认上:这段代码在什么情况下会不成立?改动的范围有没有超出我的预期?
这不是我的个人体感,有实验佐证。研究机构 METR 找了一批资深开发者做对照实验:使用 AI 工具的那组,实际完成时间比自己动手慢了 19%,而他们事前预计自己会快 24%。
快慢之间的 43 个百分点差在哪?我的理解是:生成的时间被压缩了,确认的时间一点没少。错觉来自"写"的部分——prompt 一发,代码唰唰地出来,体感极快;瓶颈藏在"验"的部分——你得逐个回答"它对不对",而这件事没有任何加速。
所以验收才是现在真正的硬技能。它至少分三层:
下面 5 个必验项,就是围绕后两层来的。
拿我常写的需求举例。在 Claude Code 里丢一句"实现一个用户列表,支持关键词搜索",一两分钟后拿到这样的组件:
function UserList({ keyword }: { keyword: string }) {
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
fetch(`/api/users?q=${keyword}`)
.then((r) => r.json())
.then(setUsers);
}, [keyword]);
return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}
类型齐全,渲染正常,输入关键词立刻有结果。按"功能路径"这一层,它已经完成了。但拿 5 个必验项过一遍,问题全在里面。
第一项:三态——加载、空、错误。 AI 默认只写成功路径。断网一次、造一批空数据、让接口返回一次失败,分别看页面呈现什么。这个组件三个分支都没有:加载中是白屏,空数据是空白,请求失败是静默——用户只会觉得"页面坏了"。
第二项:边界值——空、超长、快慢。 空关键词发不发请求?输入两百个字符的搜索词,URL 参数没编码会不会出问题?快速连续输入时,前一个慢请求的响应回来,会不会覆盖掉新结果?最后这个是经典竞态,搜索类功能的高发事故。
第三项:清理——卸载之后还活着的东西。 组件卸载后,在途请求还在飞,响应回来往一个已经不存在的组件里 setState。控制台的 warning 只是最轻的后果。验收动作很具体:切走页面,打开 Network 面板,看请求有没有被取消。
第四项:假类型——类型对,不代表数据对。 r.json() 的结果直接进了 setUsers,中间没有任何校验。接口哪天把返回结构包了一层 { code, data },TypeScript 不会报错——运行时的数据和编译时的类型声明,本来就是两回事。验收时搜一遍 any、as 和非空断言,看类型是真的在把关,还是只在哄你安心。
第五项:回归范围——diff 里有没有你没让它碰的东西。 这一项在组件之外。你让它改列表页,它顺手把共享的 formatDate 改了签名,因为它判断"这样更通用"。生成速度越快,一次带出的改动越多。验收动作:先用 git diff 圈出改动范围,凡是共享工具函数、公共样式、全局配置,逐行看。
5 项过完,这个"几分钟就完成"的组件,大概还要再花几十分钟才能提交。这就是时间账的真相。但换个角度想:这几十分钟里做的判断,恰恰是 AI 替代不了的那部分。
上面是事后验收。更划算的做法,是让验收标准在生成之前就存在——直接写进需求描述:
实现一个用户列表,支持关键词搜索。
验收标准(完成后逐条自查,并在回复里标注结果):
1. 加载中、空数据、请求失败三种状态都有对应 UI
2. 关键词变化时取消上一次未完成请求,旧结果不得覆盖新结果
3. 组件卸载后不得更新状态,不得保留在途请求
4. 请求参数需编码;响应结构先校验再使用
5. 只允许改动 UserList 相关文件,不得修改共享工具函数
完成后输出:改动过的文件列表,以及上述每一条的自查结果。
这套模板的效果比我预期的好,最明显的两点:
一是返工率降下来了。三态、竞态、清理这些以前靠"我忘了说"的事情,现在成了需求的一部分,AI 生成第一版就会带上。
二是自查结果本身就是情报。让它逐条标注,它经常会在第 3 条老老实实写"未处理"——它知道这条标准,只是默认你没提就不做。哪些是能力问题,哪些是沟通问题,自查结果会告诉你。
但要把边界说清楚:模板不转移责任。AI 的自查是用来降低返工的,不是替你验收的。最后一道人工抽验永远要在——验收标准写得再细,也没有人能替你回答"这个错误提示用户能不能看懂"。
| 必验项 | 验收动作 | 在抓什么 |
|---|---|---|
| 三态 | 断网一次、空数据一批、看加载中呈现 | 只写成功路径的实现 |
| 边界值 | 空输入、超长输入、快速连续输入各来一次 | 竞态、参数未编码、极端输入崩溃 |
| 清理 | 卸载组件,看 Network 里请求是否取消 | 在途请求、残留、定时器 |
| 假类型 | 搜 any、as、非空断言,看响应有无校验 | 类型声明和运行时数据脱节 |
| 回归范围 | git diff 圈改动,共享代码逐行看 | 顺手优化带出的外溢改动 |
用 AI 之前,前端的价值主要体现在实现上:谁能把功能写出来,谁就有产出。用 AI 之后,实现的边际价值被压薄了,真正拉开差距的变成两件事:能不能把"什么算对"说清楚,以及能不能高效地确认它。
验收标准写得清楚的人,敢把需求整段交给 AI,然后只做有依据的抽验;写不清楚的人,只能对着 AI 的输出逐行看——那比自己去写还慢。METR 实验里那 43 个百分点的错觉,一半就来自这里:没有标准,"看起来完成了"和"完成了"之间就没有刻度。
所以,别把精力全花在打磨 prompt 的措辞上。prompt 的上限,取决于你在里面放了多少验收标准。
你的验收底线画在哪?哪些必须人眼过一遍,哪些敢直接交给测试用例?评论区聊聊你的清单——你的一条必验项,可能正好补上别人缺的那条。