我用 AI 写完一个需求后才发现,最难的不是 prompt,而是验收

现在写需求的流程已经变成这样:在 Claude Code 里把需求描述清楚,它直接把组件、样式、请求逻辑一起生成出来,主流程几分钟就能跑通。

真正让我在提交前停下来的,从来不是"它写得快不快",而是另一个问题:我怎么确认这份代码达到了能提交的标准?

用得越久我越清楚一件事:prompt 决定产出速度,验收决定能不能提交。这篇把我自己正在用的验收方法整理出来:5 个必验项,加一份把验收标准直接写进 prompt 的模板。

先算一笔时间账:写的时间没了,验的时间还在

以前的分配大致是八分写、两分验:代码是自己一行行敲的,敲的过程中脑子已经顺带过了一遍,验收只是收尾。

现在倒过来了。生成只占几分钟,剩下的大块时间全花在确认上:这段代码在什么情况下会不成立?改动的范围有没有超出我的预期?

这不是我的个人体感,有实验佐证。研究机构 METR 找了一批资深开发者做对照实验:使用 AI 工具的那组,实际完成时间比自己动手慢了 19%,而他们事前预计自己会快 24%。

快慢之间的 43 个百分点差在哪?我的理解是:生成的时间被压缩了,确认的时间一点没少。错觉来自"写"的部分------prompt 一发,代码唰唰地出来,体感极快;瓶颈藏在"验"的部分------你得逐个回答"它对不对",而这件事没有任何加速。

所以验收才是现在真正的硬技能。它至少分三层:

  1. 功能路径:主流程能不能跑通。这层 AI 做得最好,也是"完成错觉"的主要来源。
  2. 边界条件:输入走到极端、状态停在中间、请求时序错开时,代码还能不能成立。
  3. 回归范围:这次改动有没有顺手动了不该动的东西。

下面 5 个必验项,就是围绕后两层来的。

一次典型的验收:AI 给的列表页缺了什么

拿我常写的需求举例。在 Claude Code 里丢一句"实现一个用户列表,支持关键词搜索",一两分钟后拿到这样的组件:

tsx 复制代码
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 不会报错------运行时的数据和编译时的类型声明,本来就是两回事。验收时搜一遍 anyas 和非空断言,看类型是真的在把关,还是只在哄你安心。

第五项:回归范围------diff 里有没有你没让它碰的东西。 这一项在组件之外。你让它改列表页,它顺手把共享的 formatDate 改了签名,因为它判断"这样更通用"。生成速度越快,一次带出的改动越多。验收动作:先用 git diff 圈出改动范围,凡是共享工具函数、公共样式、全局配置,逐行看。

5 项过完,这个"几分钟就完成"的组件,大概还要再花几十分钟才能提交。这就是时间账的真相。但换个角度想:这几十分钟里做的判断,恰恰是 AI 替代不了的那部分。

更省力的做法:把验收标准写进 prompt

上面是事后验收。更划算的做法,是让验收标准在生成之前就存在------直接写进需求描述:

text 复制代码
实现一个用户列表,支持关键词搜索。

验收标准(完成后逐条自查,并在回复里标注结果):
1. 加载中、空数据、请求失败三种状态都有对应 UI
2. 关键词变化时取消上一次未完成请求,旧结果不得覆盖新结果
3. 组件卸载后不得更新状态,不得保留在途请求
4. 请求参数需编码;响应结构先校验再使用
5. 只允许改动 UserList 相关文件,不得修改共享工具函数

完成后输出:改动过的文件列表,以及上述每一条的自查结果。

这套模板的效果比我预期的好,最明显的两点:

一是返工率降下来了。三态、竞态、清理这些以前靠"我忘了说"的事情,现在成了需求的一部分,AI 生成第一版就会带上。

二是自查结果本身就是情报。让它逐条标注,它经常会在第 3 条老老实实写"未处理"------它知道这条标准,只是默认你没提就不做。哪些是能力问题,哪些是沟通问题,自查结果会告诉你。

但要把边界说清楚:模板不转移责任。AI 的自查是用来降低返工的,不是替你验收的。最后一道人工抽验永远要在------验收标准写得再细,也没有人能替你回答"这个错误提示用户能不能看懂"。

验收清单速查表

必验项 验收动作 在抓什么
三态 断网一次、空数据一批、看加载中呈现 只写成功路径的实现
边界值 空输入、超长输入、快速连续输入各来一次 竞态、参数未编码、极端输入崩溃
清理 卸载组件,看 Network 里请求是否取消 在途请求、残留监听、定时器
假类型 搜 any、as、非空断言,看响应有无校验 类型声明和运行时数据脱节
回归范围 git diff 圈改动,共享代码逐行看 顺手优化带出的外溢改动

从写代码的人,变成定标准的人

用 AI 之前,前端的价值主要体现在实现上:谁能把功能写出来,谁就有产出。用 AI 之后,实现的边际价值被压薄了,真正拉开差距的变成两件事:能不能把"什么算对"说清楚,以及能不能高效地确认它。

验收标准写得清楚的人,敢把需求整段交给 AI,然后只做有依据的抽验;写不清楚的人,只能对着 AI 的输出逐行看------那比自己去写还慢。METR 实验里那 43 个百分点的错觉,一半就来自这里:没有标准,"看起来完成了"和"完成了"之间就没有刻度。

所以,别把精力全花在打磨 prompt 的措辞上。prompt 的上限,取决于你在里面放了多少验收标准。

你的验收底线画在哪?哪些必须人眼过一遍,哪些敢直接交给测试用例?评论区聊聊你的清单------你的一条必验项,可能正好补上别人缺的那条。

相关推荐
申行1 小时前
Vue 3 + DYMO Connect Framework 实战:从标签模板到打印服务的完整实现
前端
两只羊ovo1 小时前
Vue 3 + DeepSeek 流式输出实战:从“干等”到“打字机”体验
前端·vue.js
Yeyu1 小时前
车载多 App 同屏渲染(二):SurfaceControlViewHost 跨进程
前端
樊小肆1 小时前
离谱,每轮请求 25% 的 token,竟在重发模型想完就扔的内心独白
前端·人工智能·agent
小妖现世1 小时前
前端面试复习笔记:React 高频题 + JS 手写题
前端
holidaypenguin1 小时前
Windows 本地 HTTPS 证书生成指南
前端
酷酷的逗逗乐1 小时前
前端转 Agent 开发 · 第六节
前端·程序员
回家吃饭去吧1 小时前
WebAssembly 深度解析:前端性能的最后一块拼图
前端
爱勇宝1 小时前
没有 Fn 键关触控板?我做了一个双击即用的 Windows 小工具
前端·后端·程序员