AI编程返工率高的真凶:需求描述太薄,用四要素模板一次讲清

发布时间:2026/9/7 23:23:56
AI编程返工率高的真凶:需求描述太薄,用四要素模板一次讲清 先说一个让我血压飙升的场景。上个月我让AI编程助手写一个用户管理列表页需求就一句话“帮我写一个用户列表页面支持搜索和分页。”AI十分钟就生成了页面看起来像模像样表格有了、搜索框有了、分页器也有了。结果一联调问题全冒出来了——搜索是前端filter硬过滤根本不是请求后端接口分页是假分页一次性把全量数据拉到内存里翻页没有loading状态、没有空数据提示接口字段跟后端实际返回对不上最离谱的是删除用户这种基础操作它只做了个弹窗确认接口压根没调。我当时第一反应是这AI也太拉了。但冷静下来复盘才发现真正的问题出在我身上——我给它的是一句“一句话需求”这句话背后至少藏着十几个没有回答的问题用户列表的数据从哪来搜索走前端还是后端分页是服务端分页还是客户端分页哪些字段要展示需不需要批量操作接口还没定怎么办加载中、失败、空数据这些状态要不要处理从那次之后我系统性地研究了三个月AI编程的返工规律最后总结出一个很朴素的结论AI编程返工率高绝大多数情况不是模型能力不行而是需求描述太“薄”。后来我开始用“需求四要素”的方法组织所有交给AI的任务描述——背景与目标、功能与行为、边界与约束、验收标准——返工率肉眼可见地下降。这篇文章就把这个方法完整拆开讲清楚附上我实测的对比数据和可以直接抄的模板。如果你也在用AI写代码、天天跟返工掰手腕这应该是你今年最值得花十分钟读完的一篇实操文章。1. 返工的真凶不是模型是需求描述太“薄”1.1 一个让人血压升高的典型场景我做了一个小实验让AI实现“用户注册”功能。第一版需求描述是“写一个用户注册页面。”AI生成的代码里密码字段用的是明文的typetext没有确认密码框没有校验手机号格式提交按钮也没有防止重复点击的逻辑。更要命的是它自己定义了一整套REGISTER_API的假想接口跟后端文档完全对不上。这不是个例。在我统计的过往两个月任务里凡是只给了“标题式需求”的任务平均要来回拉扯四到五轮才能验收而每拉扯一轮AI还会引入新的问题——比如改好了校验又把某个按钮的点击事件改没了。这种“修东墙拆西墙”的循环是AI编程最大的隐性成本。为什么会这样我得解释一下背后的原理。大语言模型不是数据库检索它本质上是“按概率续写下一个token”。给它一句话需求它就按照训练语料里“最常见的注册页面长什么样”来续写。而“最常见”恰恰意味着“什么都带一点什么都是泛化版本”。泛化版本放到真实项目里大概率跟你的业务逻辑、接口协议、UI规范打架——返工就这么来了。1.2 一句话需求背后藏着十几个未回答的问题我把“写一个用户注册页面”这句话拆成了下面这些问题注册字段有哪些手机号邮箱用户名昵称密码规则是什么最少几位要不要大小写混合校验时机输入时实时校验还是提交时统一校验接口地址和请求方式是啥参数命名规则返回结构什么样登录成功之后跳哪token存哪里要不要验证码图形验证还是短信验证重复提交怎么防接口失败怎么提示loading态怎么处理适配哪些浏览器表单样式走组件库还是自定义是不是注册完还要自动登录这些问题AI一个都没问我因为它没法问它只能猜。猜对了算运气好猜错了就是返工。每一个没回答的问题都是埋在地里的雷等你在联调、走查、测试阶段一颗颗踩响。1.3 为什么AI会一本正经地跑偏这里有个很反直觉的点AI跑偏的时候往往是“自信满满”的。它不会告诉你“这个需求我没完全理解我做了几个假设”它只会默默地在代码里写下const config { apiHost: http://localhost:3000 }看起来无比正确。这其实是语言模型的概率特性决定的。当信息不足时模型会选择概率最高的补全路径而这个路径来自它训练数据里的海量通用代码。你自己项目里的特殊约定、业务含义、历史包袱在它的概率分布里都是“低频事件”自然不会被选中。所以你会发现AI生成的代码在“通用场景”下越漂亮掺进你的“特定业务”时就越容易水土不服。想通这一点之后我意识到一个关键结论我不能指望AI问我要信息我必须主动把信息塞给它。需求四要素就是干这个用的——在动手之前把AI做决策需要的“上下文”一次性喂足让它的概率空间从“一万种常见写法”收敛到“你唯一想要的那种写法”。下面我详细拆解这四个要素。2. 需求四要素到底是什么每一要素精确打击一类返工2.1 背景与目标先告诉AI“为什么做”第一个要素是背景与目标。很多人写需求喜欢直接从功能细节开始但AI面对一堆功能指令时缺乏“这件事的语境”很容易做出不合实际的取舍。举个例子。你说“用户列表页要把状态列展示出来”如果AI不知道这是“内部运营后台”它可能会把状态做成一个纯文本让小字如果它知道“运营每天要看几十上百条记录、需要快速扫一眼识别异常”它就会自动把状态做成高亮Tag、加上颜色语义甚至考虑表格密度和排序列。背景与目标这一栏要回答三个问题这个功能给谁用内部员工还是外部用户专业程度如何它解决什么业务问题前置状态是什么成功后是什么场景有没有依赖的现存功能或历史包袱比如我会这样写背景这是给公司运营团队使用的订单管理后台目前订单列表在 order-list.vue 中只有基础展示功能。运营反馈无法快速筛选异常订单需要在现有页面上增加按订单状态筛选的能力。这句背景说明一添加AI就会知道这是“改造现有页面”而不是“从零新建”页面的使用人群是运营核心痛点是“快速筛选”。它生成的代码会优先考虑跟现有页面风格保持一致、用现成的筛选组件而不是自作主张重新设计一个页面。2.2 功能与行为把做的过程拆到可执行第二个要素是功能与行为这是需求的主体也是大多数人唯一会写的部分。但问题在于大家写得太笼统。“支持搜索”四个字和下面的写法对AI来说是天壤之别搜索框放在表格上方宽度300px占位文案“请输入订单号/客户名称”输入后点击“搜索”按钮或按回车触发查询搜索条件变化后重置页码为1重新请求接口前端不提前过滤数据所有筛选通过后端接口参数完成看出区别了吗“支持搜索”描述的是“结果”而上面四条描述的是“行为路径”。AI是逐token生成代码的你给它行为路径越完整它生成出来的代码就越贴近你的预期需要你在review阶段补位的脑力就越少。功能与行为的写作要点操作流程写成分步列表用户先看到什么、能做什么、操作后发生什么1→2→3→4。数据流向写清楚数据从哪个接口来、用什么参数、响应结构长什么样、前端存到哪里。状态枚举要完整接口要处理的四种核心状态——正常态、加载态、空态、失败态直接告诉AI要不要做以及各自展示什么。交互细节别嫌啰嗦按钮禁用条件、回车提交、弹窗确认、二次操作提示。细节越明确AI越不需要猜。2.3 边界与约束在动手前划好红线第三个要素是边界与约束这是最容易被忽略、但返工收益最大的部分。AI默认的心态是“把这件事做得越多越完整越好”所以它特别喜欢“超纲发挥”你让它做个搜索框它顺手给你加了个搜索历史你让它写个接口它自己封装了一套请求工具类跟你项目的现有HTTP库冲突你让它改一个按钮它把整个文件重排了一遍格式review起来眼睛都快瞎了。边界与约束就是用来“踩刹车”的。它告诉AI明确不要做什么不做忘记密码、不做验证码、不做导出必须沿用现有技术栈和组件库不要在Vue2项目里写Vue3语法不要引入新的npm包禁止触碰的现有代码范围不要修改路由守卫、不要动公共组件、不要改变原有接口的响应结构性能和兼容性硬指标列表超过1000条必须分页、只兼容Chrome和Safari最新两个版本我个人的经验是边界与约束至少能消掉30%的返工。因为AI最常犯的错误不是“做不出来”而是“做了你没让它做的事”然后你还得花时间要么改掉它、要么解释为什么不需要。2.4 验收标准让代码可测试、可交付第四个要素是验收标准。如果说背景与目标是给AI“导航方向”功能与行为是“画路线图”边界与约束是“设禁行区”那验收标准就是“终点线”——你站在终点告诉它什么情况算到了。很多人觉得验收标准是测试阶段的事写需求时不用管。但AI编程的场景恰恰相反——验收标准应该前置到需求描述里因为AI在生成代码时会主动对着验收标准“自查”相当于一个内置的自测环节。验收标准怎么写才有效核心是“可执行、可验证”每条都是AI能自己检查的硬指标手机号格式错误时输入框下方2秒内出现红色提示文案点击登录后按钮置灰并显示loading接口返回前不可重复点击接口返回401时页面跳转回登录页空数据时表格区域显示“暂无数据”占位图批量禁用成功后表格自动刷新且被选择行状态变为disabled把这种验收清单贴进需求里AI生成完代码会自己过一遍很多明显的问题在第一次生成时就被它自己规避了。这一点是四要素里“性价比”最高的下文实测数据里你能看到它的效果。3. 同一需求三种写法实测返工率从80%降到10%3.1 测试环境与衡量口径为了验证“需求四要素到底有多少用”而不是凭感觉拍脑袋我做了一组对照实验。实验环境同一款AI编程助手、同一个代码仓库、连续一个月内完成10个同类型任务前端CRUD页面开发我把它们随机分成三组写法每组3到4个任务写法一一句话需求如“写一个角色管理页面”写法二只写功能与行为不加背景、边界、验收写法三完整四要素衡量指标有三个首次生成后需返工的比例返工率、平均每个任务从生成到达到验收标准的往返轮次、人工评审时发现的缺陷总数。参与测试的任务都是真实业务难度相近AI工具版本全程固定。3.2 写法一一句话需求对照组对照组每个任务的需求就是一句话。结果意料之中4个任务全部返工首次生成就能直接用的为0个平均每个任务来回4.25轮才达到验收标准评审阶段场均发现5.5个缺陷。最典型的案例是“角色分配权限”这个页面。AI生成后权限树直接写死在前端配置文件里后端角色和权限的关联接口一概没有。我问它“权限树数据从哪来”它回答“mock数据”。我又得花两轮告诉它怎么接真实接口还要自己动手改权限树的层级结构和选中逻辑。一句话需求组的总耗时含生成、评审、返工修改平均每个任务约47分钟其中真正的“生成时间”只占5分钟剩下42分钟全在“发现偏差→指出偏差→等待修改→验证”的循环里消耗掉了。3.3 写法二有功能但没边界中间态第二组我写了比较详细的功能描述但故意不写背景、边界和验收标准。例如角色管理页面我会写左侧是角色列表、右侧是权限树、保存时提交选中节点、接口地址/api/roles/{id}/permissions等。结果比一句话好不少返工率从100%降到了约60%平均轮次降到2.75轮。但出现了两类新问题一是AI“过度设计”。功能描述里没提“不要做什么”AI自作主张给权限树加了“半选状态同步”“父子联动动画”“节点拖拽排序”这些我没要求的能力。有些确实加了觉得还行但开发时间成本上去了而且这些功能后续维护都是负担。二是因为没写验收标准AI不知道自己做的“算不算完”。它的代码经常在“表面功能”上满足了我的描述但边界情况一塌糊涂角色列表超过20条时没有滚动或分页、树节点展开状态刷新后丢失、点击保存时没有做并发保护。这个结果说明一个道理光写清“做什么”还不够“不做什么”和“怎样才算完”同样决定了返工率。3.4 写法三完整四要素实验组第三组我用了完整四要素写法每个任务在动手前花三五分钟把背景、功能、边界、验收写清楚。结果让我自己都有点意外3个实验组任务里2个一次通过验收1个只经过一轮小幅修改就达标返工率按“需要返工的任务占比”来算是约33%但如果按“真正需要大改的任务占比”算只有0个。那个唯一经过一轮修改的任务问题出在验收标准里有一条没写清楚——“权限树节点默认展开到二级”。我写了“默认展开层级”但没写清“二级”这个具体数字AI按自己理解展开了全部层级。我补上“展开到二级根节点收起”后一轮就改好了。实验组的评审缺陷数也低得离谱平均每个任务只有0.7个且全是样式微调级别的没有一个是逻辑性、架构性缺陷。几乎不用再花时间帮AI“擦屁股”。3.5 三轮测试结果对比表我把三轮结果汇总成一张表可以很直观地看到差异需求写法任务数返工率需返工/总数平均往返轮次平均缺陷数平均总耗时一句话需求4100%4/44.25轮5.5个47分钟只写功能行为3约67%2/32.75轮2.3个28分钟完整四要素3约33%1/31.0~2.0轮0.7个14分钟注意第三组的“33%返工率”里包含了“一轮小幅修改”的情况如果严格按“需要大的逻辑重写”定义返工这个数字其实是0。换句话说四要素写法把这批任务的返工率从100%降到了接近0耗时压到原来的三分之一。虽然样本不大但结合我后来三个月的长期使用经验这个结论是稳定的。4. 可直接照抄的四要素Prompt模板与改造示例4.1 通用模板具体到实操环节我把自己现在每天在用的模板贴在下面。这个模板你可以直接复制替换成自己的内容就能用。格式上我用“标签加分条”的形式因为实际测试下来AI对结构化的Markdown分条列表理解得最好比一大段散文式的描述效果好得多。【背景与目标】功能使用人群谁在用这个功能内部/外部要解决的问题现在是什么状态痛点是什么做完之后是什么状态前置依赖依赖哪些现有功能/接口/数据表【功能与行为】操作流程1. 用户先看到什么2. 操作什么3. 发生什么反馈页面模块/接口明细包含哪些区域、字段、参数、返回结构数据流向数据来源、请求方式、存储位置、更新时机状态齐全正常态 / 加载中 / 空数据 / 失败分别怎么展示【边界与约束】明确不做列出本次范围外的事技术栈使用的框架、组件库、请求库、语法版本不要修改现有的哪些文件/逻辑保持不动性能与兼容并发、分页、体积、浏览器要求【验收标准】用具体用例描述输入什么、操作什么、期望什么结果代码要求命名规范、注释要求、不允许使用什么每一条都要可验证4.2 前端页面类需求示例前面那个“用户注册页面”我按模板重写了一遍效果完全不一样【背景与目标】 这是面向C端用户的产品注册页用户通过手机号注册后自动登录并跳转到首页。现有项目已封装好 axios 实例request后端注册接口已就绪。【功能与行为】页面顶部展示产品Logo和标题“注册”表单包含三个字段手机号、密码、确认密码手机号输入框失焦时校验格式11位、1开头格式错误时下方红色提示密码至少8位需包含字母和数字确认密码与密码不一致时提示“两次输入的密码不一致”点击“注册”按钮后调用POST /api/register参数为{ phone, password }请求期间按钮置灰、显示loading文案防止重复提交成功后提示“注册成功”把返回的 token 存入 localStorage跳转/home失败时展示后端返回的错误消息【边界与约束】不做图形验证码、短信验证码、忘记密码、登录功能登录页已有使用现有request实例不重新封装请求库样式使用项目现有的 antd-mobile 组件不新增UI库不修改路由文件只新增本页面路由【验收标准】输入 11 位不是1开头的手机号失焦后出现“请输入正确的手机号”输入两次不一致的密码点击注册后提示“两次输入的密码不一致”不发请求正常提交后localStorage 中出现 token接口失败时提示错误信息按钮恢复可点击生成页面在 Chrome 和 Safari 最新版显示正常这套描述我实测生成出来的代码几乎不需要改动就能直接用。关键的接口调用、校验规则、loading控制全部一次到位。4.3 后端接口类需求示例后端接口的需求描述重点要放在参数、返回结构和异常处理上【背景与目标】 为管理后台提供订单列表查询接口供订单管理页面调用。订单数据在orders表中目前已有基础的分页查询工具类PageHelper。运营需要按状态和时间范围筛选订单。【功能与行为】接口路径GET /api/admin/orders请求参数page默认1、pageSize默认20、status可选、startDate、endDate时间戳返回结构{ code: 0, message: success, data: { list: [...], total: 100 } }排序按createTime倒序鉴权请求头Authorization携带管理员token无token返回401参数校验pageSize最大100超过返回参数错误startDate大于endDate返回参数错误【边界与约束】不做订单导出、不做订单详情接口使用现有PageHelper和统一返回结果类ResultT不新造轮子不修改orders表结构SQL只查询必要字段不使用select *【验收标准】用 curl 携带token调用返回code0且data.total与数据库总数一致不带token调用返回401status传无效值时返回参数错误提示pageSize1000时返回参数错误列表按createTime倒序排列4.4 存量代码修改类需求示例存量代码修改是四要素最被低估的应用场景。改现有代码时AI最大的风险是“改一个地方带崩另一个地方”所以边界与约束这一块要写得更重【背景与目标】 现有订单列表页order-list.vue已上线用户需要批量禁用订单能力。当前表格支持单选操作新增批量操作后需要再给表格增加复选框列。【功能与行为】表格首列增加复选框表头有“全选”按钮选中至少1条后表格上方出现“批量禁用”按钮点击按钮弹出确认框“确定禁用选中的 N 个订单吗”确认后调用POST /api/orders/batch-disable参数为{ ids: [...] }成功后ElMessage.success提示并刷新列表清空选中状态失败时提示错误列表不刷新选中状态保留【边界与约束】只修改order-list.vue和它用到的 store 文件不修改其他页面组件不改变现有单条禁用逻辑和接口保持现有 el-table 和 ElMessage 的UI风格不引入新的npm包【验收标准】勾选2条数据点击批量禁用并确认请求负载包含两个id成功后列表刷新且两行状态变为 disabled不勾选任何行时批量禁用按钮不可见或置灰接口失败时出现错误提示勾选状态保持不变原有单行禁用功能不受影响这种“存量修改型”需求用四要素写清楚之后AI给出的 diff 非常可控review 只需重点看新加的逻辑不用担心它顺手把整段表格组件重写一遍。5. 实践中容易踩的四个坑以及我的应对方式5.1 坑一四要素写成了小作文AI抓不住重点我一开始也走过极端把四要素写得事无巨细背景写了三行、功能写了二十条排版密得像技术方案文档。结果AI反而变笨了经常顾此失彼。后来我总结出一个原则每个要素控制在3到8条超过8条就要考虑拆分任务。如果一个功能细节多到写不完说明这个任务本身就太大了应该拆成两到三个子任务分多次对话完成。另外每条尽量一句话讲完一个动作不要在一行里塞两个逻辑比如“点击按钮后调用接口且成功后跳转且失败后提示”——这种复合描述让AI很难准确映射到代码分支。5.2 坑二验收标准写成了空话“代码要高质量”“性能要好”“体验要流畅”“命名规范”这类验收标准等于没写。AI看到这些词的时候无法把它们转化为可执行的检查项所以大概率还是按自己的理解生成。我把验收标准的写法纠正成了“具体输入操作期望输出”的模式。不要写“性能要好”要写“列表渲染1000条数据时页面无明显卡顿滚动帧率不低于50fps”不要写“命名规范”要写“接口路径使用 RESTful 风格动词不放进URL”。AI是能吃下这种指令的而且吃下之后会体现在代码里。5.3 坑三边界和约束自相矛盾有一次我写约束说“沿用现有请求封装 request不要重新封装”验收标准里却写“所有接口请求需要统一在请求拦截器里加token”。仔细一想加token是修改 request 封装内部逻辑这不就跟“不要重新封装”冲突了吗AI生成的代码果然纠结了——它既不想动 request又想在拦截器里加逻辑最后生成了个在页面里手动拼header的折中方案丑得没法看。解决方案很笨但很有效提交前自己把四要素从头到尾读一遍重点交叉检查边界与验收之间有没有冲突。如果确实需要改公共封装就把“修改 request 的拦截器”明确写进功能与行为里同时边界里注明“只改拦截器不改其他方法签名”。5.4 坑四连续对话中需求被“污染”旧需求混进新任务同一个对话窗口里我连续让它改完一个页面又新建另一个功能结果新功能的代码里居然带着旧页面的样式片段和变量名。这就是“上下文污染”——AI把对话历史里旧任务的需求信息错误地套用到了新任务上。我的应对方式是一个任务开一个新对话四要素完整复制进去。如果是同一个任务的迭代修改也要用“只改第X条”的方式精确定位而不是把整个需求重贴一遍否则AI会分不清哪些是更新后的、哪些是作废的。另外每次新对话的第一句我会明确写“这是一个全新任务请忽略之前的任何对话内容”进一步切断上下文串扰。6. 用了一段时间之后的个人体会说实话需求四要素这个框架本身一点都不高深拆开看都是常识。但真正用了三个月之后我发现它最大的价值其实不在“哄AI”——而在逼我自己先把需求想清楚。以前我写需求是“想到哪写到哪”脑子里模模糊糊觉得“大概就是做个筛选功能吧”然后扔给AI去填空。AI填出来不对我骂它笨其实是我自己的需求脑图里连“筛选条件要不要重置页码”这种基础问题都没想好。现在每次写四要素我必须把背景、功能、边界、验收过一遍脑子很多原本在开发中期才会发现的矛盾在写需求的五分钟里就暴露了。哪怕完全不考虑AI光凭这个“想清楚”的过程返工率也该降下来。当然四要素也不是万能药。简单到“把按钮颜色改成主题蓝”这种任务写全四要素纯属浪费时间一条功能描述加一条验收标准就够了。我现在的习惯是十分钟能说清的任务写两要素需要跨文件改动、涉及业务流程的任务才用完整四要素。判断标准很简单——你闭上眼睛能不能在脑子里把代码跑一遍能跑明白就少写点跑不明白就老老实实把四要素补齐。最后分享一个小技巧。我把自己常用的几类任务——前端页面、后端接口、存量改造、BUG修复——都做了固定的四要素模板存成文档。每次新任务只需要在模板里填空五分钟就能产出一份高质量的需求描述。写多了之后你还会发现AI编程的体验上限大概率取决于你的需求描述下限。把需求说清楚这个基本功补上之后AI带来的效率提升是实打实的。