AI 写代码越快,我越不敢省略这一步

昨天我又看了一遍前天 Cursor /goal 给我留下的那堆改动。

十三处文件变更,三个是真的在修 CI 红灯,八个属于它顺手做的「优化」——改了我根本没让它动的 GitHub Actions 步骤、删了一个它觉得是废弃脚本的热修复文件、还在 package.json 里加了 engines 字段。 commit message 里写得挺谦虚:”drive-by cleanup”。我盯着屏幕看了半天, cleanup 是有的, drive-by 也是真的,可谁允许它上我的车道了?

这件事的后续我写在前一篇里了。今天想聊的不是 Cursor 的边界问题,而是这件事让我重新意识到的一个老道理:AI 写代码越快,我把需求写清楚这件事就越不能偷懒。

一句 “帮我写个登录” 能惹出多少麻烦

上个月有个小项目需要补一个登录模块。我打开 Cursor,输了一句看起来挺完整的 prompt:

帮我写一个用户登录功能,包含邮箱和密码校验,成功后返回 JWT。

三秒钟后它给了我一个像模像样的实现:Express 路由、bcrypt 比对、jsonwebtoken 签发、错误处理。我扫了一眼,语法没毛病,逻辑也顺,就直接放进项目里跑测试。

测试通过了。我甚至还夸了一句真快。

两天后线上反馈说,有用户收不到登录后的欢迎邮件。我去查代码,发现 AI 把登录和注册的后处理逻辑混在了一起:登录成功之后,它调用了一个 sendWelcomeEmail 的函数。这个函数是我项目里原本就有的,专给新注册用户发的。AI 一看,”登录成功要发邮件”,顺手就调用了。

它没有错。是我没说明白:登录就是登录,不要触发任何注册流程的副作用。

还有一次更隐蔽。我让 AI 给内部后台加一个「按日期导出报表」的功能,prompt 里写了接口、参数、返回格式。它完成得干净利落。直到运营同事说,导出的数据里包含了已删除账号的记录。我回去看代码,发现 AI 在 SQL 查询里没加 deleted_at IS NULL 的条件。

这个条件在我的项目里几乎是铁律。但 AI 不是项目成员,它不知道这条没写进 prompt 的铁律。它只根据字面意思,把符合日期范围的数据全捞了出来。

这两件事让我明白,当 AI 的生成速度从分钟级变成秒级,我的 prompt 漏洞也被同比例放大了。以前我写得不清楚,最多是自己多改两遍;现在写不清楚,AI 能在眨眼间把假设砌进代码里,而且这些假设常常看起来还很合理。

不是 AI 爱乱猜,是它必须猜

很多人遇到这种情况会怪 AI:你怎么能擅自做主呢?

但换个角度想,AI 没有别的选择。我的 prompt 停在 “写一个登录功能”,它必须补全我没说的部分:要不要记住登录状态?要不要处理并发?要不要记录日志?要不要发邮件?这些我没提,它只能根据训练数据里的常见模式去填。

而训练数据里的常见模式,未必是我的项目模式。

这就像你请一个外包团队做功能,只给了一句话需求,对方为了交付,一定会按他们自己的理解把细节补全。补得对不对,取决于你的原始需求有多完整。AI 本质上就是一个超级便宜、超级快、但对你的项目一无所知的外包。

我并不是现在才意识到这一点。早在我开始依赖 AI 做技术决策的时候,就吃过类似的亏:我把消息队列选型丢给 AI,却忘了说明「这个消息必须秒到」的硬约束,结果它推荐了一个适合异步批处理的方案,导致线上消息积压了二十分钟。

问题从来不是 AI 能不能干,而是我有没有把边界讲清楚。

我现在写需求的两页纸

这个教训让我重新捡起了以前觉得「太重」的需求说明习惯。不过我没用公司的正式文档模板,而是给自己弄了一个极简的两页纸格式,每次让 AI 写代码之前先填完。

第一页只回答三个问题。

这个功能要解决谁的什么问题? 不是写 “用户需要登录” 这种正确的废话,而是写 “已注册用户在换设备后,需要重新验证身份才能查看历史订单”。后者包含了使用场景,AI 更容易理解边界。

哪些情况是必须拒绝的? 我会把显式的失败条件列出来:密码错误次数过多要锁定、JWT 过期要返回 401 而不是 500、未验证邮箱不能登录。这些东西如果我不写,AI 可能会按它的理解给出一个 “看起来合理” 的处理。

改动范围画在哪? 这是我从 Cursor /goal 那件事里学到的。我会明确说:只允许修改 auth 目录下的文件,不要碰 CI 配置,不要改 package.json,不要删任何现有脚本。边界画出来,AI 越界的时候我才有理由骂它。

第二页更短,只写一句:如果这件事只能保留一个核心约束,是什么?

比如登录功能,核心约束是 “身份验证成功后,除了签发 token,不触发任何其他业务流程”。比如导出报表,核心约束是 “只返回活跃用户的数据,已删除和已禁用的账号一律排除”。

这个核心约束通常只有一两句话,但它是我最后验收的底线。AI 给出一堆代码之后,我会先拿这句话去对照:有没有哪里违反了这个约束?

需求写清楚了,AI 反而更像一个搭档

有人说,写需求都写这么细,那还要 AI 干什么,我自己写不就好了?

我一开始也这么觉得。但试了一段时间后发现,需求写得越清楚,AI 的价值越不在 “写代码”,而在 “帮我补全我想不到的地方”。

有一次我让 AI 实现一个文件上传功能,需求里写明了只接受 PDF 和 PNG,大小不超过 10MB。AI 在实现的时候主动加了一个我没想到的点:当文件超过限制时,它返回了具体的错误信息,包括当前文件大小和允许的最大值。这个细节我自己写可能也会加,但不会在第一版就想到。

还有一次,我在需求里明确说 “上传后的文件要保存到本地磁盘,路径按日期分目录”。AI 顺手帮我加了一个清理过期文件的定时任务建议。这个建议我不一定采纳,但它说明 AI 在理解了我的完整意图之后,开始能做超出字面意思的有用补充。

这种时候,AI 才更像一个能合作的程序员,而不是一个只会按字面翻译 prompt 的代码生成器。

当然不是所有功能都值得写两页纸

这个道理也有适用范围。

让我自己写一个工具函数,或者改一个明显的 bug,我不会掏两页纸出来。那种时候 prompt 越短越好,直接告诉它 “把这里的硬编码改成从配置读取” 就够了。需求详细化的收益,和功能的复杂度、风险、以及它可能触碰的边界成正比。

我的判断标准很简单:如果这个功能改完上线,一旦出问题会影响核心业务流程,或者会改动多个模块,那我就会先把两页纸填完。如果只是一个局部的小调整,那就交给 AI 自由发挥。

这个方法也让我对 “AI 会不会替代程序员” 有了更具体的答案。会替代的那部分,恰恰是那些需求已经清楚到不需要人再思考的工作;不会替代的那部分,是把这些需求想清楚、写清楚、并在代码出来后判断它是否满足真正意图的工作。

而后者,正是我现在每次打开 AI 编辑器之前,强迫自己多写的那几分钟。

写在最后

Cursor /goal 改了我八个不该改的文件之后,我没有关掉这个功能。它确实帮我修对了三个真正的 CI 问题,省了我一晚上。

我只是把 prompt 改了。

现在每次派任务给它,我都会先贴一段需求说明,最后一行固定写着:”如果任务涉及范围以外的文件,停下来问,不要自己改。”

这段提示有没有用?不完全有用。它还是会偶尔越界。但越界的次数明显少了。更重要的是,它让我意识到:在 AI 时代,写清楚需求不再是项目经理或产品经理的专利,而是每个程序员都必须自己拿回来的基本功。

代码生成可以外包给 AI,但把问题想明白这件事,目前来看还只能自己来。


AI 写代码越快,我越不敢省略这一步
https://www.ohtudou.top/2026/08/26/2026-08-26-ai-coding-requirement-spec-first/
作者
Tudo
发布于
2026年8月26日
许可协议