AI 编程正确姿势:规格先行、小步提交

AI 写代码变快之后,新的瓶颈变成了「你敢不敢合」。这一章讲的是流程纪律,不是提示词技巧:先写规格再动手、一次只改一件事、让它先解释再执行、逐行看 diff、敏感信息永不外发。遵守这五条,AI 是加速器;少一条,它就是把 bug 更快地送进主干的传送带。

规格先行:先写清输入输出与验收标准

最好的提示词不是「帮我写个函数」,而是一份能被验收的小规格。缺规格时,AI 只能猜,你也只能凭感觉验收。

规格要素要写清什么反例
输入类型、来源、取值范围、空值怎么算「输入一些数据」
输出类型、字段、格式、排序规则「返回处理结果」
边界空、超长、并发、重复调用只描述顺利路径
错误处理什么情况抛错、什么情况返回空「出错时处理一下」
验收标准用什么测试或数据算通过「看着对就行」
不做的事明确划出范围外没有范围,它就顺手重构一切
请实现一个「按用户 ID 合并重复订单」的函数,规格如下:
输入:orders 数组,每项含 orderId(string)、userId(string)、amount(number,单位分,非负)、
createdAt(ISO8601 字符串),数组可能为空,可能含 orderId 重复项。
输出:新的数组,按 userId 分组,每组输出一条:
{ userId, orderCount, totalAmount(分), firstCreatedAt, lastCreatedAt },
按 totalAmount 降序排列;入参数组不得被修改。
边界要求:
- 空数组返回空数组,不抛错;
- amount 为 0 是合法值,不能被当成缺失;
- createdAt 相同或乱序时,仍要正确取最早与最晚;
- orderId 重复时视为同一条,只计一次(以 orderId 去重)。
错误处理:字段缺失或类型不符时抛出带字段名的错误,不要静默跳过。
不做的事:不要改数据库、不要加缓存、不要改其它文件的代码。
交付:函数实现 + 至少 6 个单元测试,测试需覆盖上述每条边界要求。
先把你对规格的理解复述一遍,指出你认为有歧义的地方,等我确认后再写代码。

最后一句是关键:先让它复述规格。歧义在写代码前暴露,成本是零;写完再暴露,成本是一个下午。

小步提交:一次只做一件事

提交粒度例子评价
太粗一个提交里同时改字段命名、加缓存、修 bug出问题无法单独回滚
合适一个提交只做「字段重命名」并保证测试通过可回滚、可审查
太碎每改一行提交一次历史噪音大
# 让 AI 只改这一件事,改完立刻确认范围与测试
git status --short
git diff --stat                     # 期望只出现 1~3 个文件
# 跑测试,绿了再提交
npm test -- --runInBand 2>/dev/null || go test ./... || pytest -q
git add -p                          # 逐块挑选,避免把无关改动一起提交
git commit -m "refactor: 统一订单金额字段命名为 totalAmount"

一条实用规则:改动的文件数超过预期就要停下来问为什么。要让 AI 一次只做一步,可以在提示词里写死:

本次只做一件事:把 order 模块里 amountInCents 字段统一改名为 totalAmount。
要求:
1) 先列出你打算修改的全部文件与每处改动的行号,等我确认;
2) 只改这一个字段名,不顺手改格式、不加注释、不重构其它逻辑;
3) 改完运行测试并贴出结果;如果测试失败,只报告失败原因,不要自行扩大改动范围;
4) 如果发现还有别的明显问题,写进「建议后续处理」列表,本次不要动。

让 AI 解释再改

看不懂的代码不要合。让它在动手前把「为什么这么改」讲清楚,比事后读一百行 diff 便宜得多。

在修改之前,请先回答四个问题:
1) 这段代码原本的问题是什么?请引用具体行号与代码片段;
2) 你打算怎么改?分步骤说明,每步指出会影响哪些函数或模块;
3) 这个改动可能导致哪些行为变化?特别说明可能被破坏的现有功能;
4) 有没有更小的改法?如果有一行改动就能解决的方式,优先给出来。
我确认之后你再动手。如果我的判断和你的不同,请指出我的理解错在哪里,而不是顺着我说。

review 每一行 diff

AI 生成的代码,签字的人是你。合入前按固定清单过一遍:

git diff --stat                 # 先看范围,防止它偷偷改了别的文件
git diff                        # 逐行读,重点看下面清单里的项
git diff --cached --name-only   # 确认暂存区里没有多余文件
检查项具体看什么
范围是否出现了与本次任务无关的文件改动
逻辑边界条件、空值、循环边界、并发与重入
错误处理异常是否被吞掉、失败是否被当成成功返回
副作用是否偷偷改了全局状态、配置、数据库结构
安全是否打印了敏感字段、是否拼接了 SQL 或路径
依赖是否引入了新依赖、新依赖是否必要且可信
测试新增逻辑是否有测试,测试是否真的会失败(故意改坏验证一次)
风格是否符合项目既有写法,而不是它自己的偏好

不要贴密钥与生产数据

千万不要贴换成什么
真实密钥、令牌、口令<API_KEY> 之类占位符
生产库连接串db.internal:3306 之类的假地址
客户真实数据自己构造的假数据,保持字段结构一致
完整日志只留报错行,去掉账号、手机号、身份证
# 提交前扫一遍疑似密钥
git diff --cached -U0 | grep -nE '(AKIA[0-9A-Z]{16}|BEGIN [A-Z ]*PRIVATE KEY|(password|passwd|token|api[_-]?key)\s*[:=]\s*\S{8,})'
# 贴日志前先做替换
sed -E 's/1[3-9][0-9]{9}/<PHONE>/g; s/[0-9]{17}[0-9Xx]/<IDCARD>/g' app.log > app.safe.log

常见坑

后果规避
一个提示词让它干五件事改动面大,出问题无法定位一次一件事,分多次提交
没写验收标准无法判断是否完成规格里写明测试与数据
只看它说「已完成」漏改、静默失败自己看 diff 与测试输出
测试是它写的就直接信测试可能只覆盖顺利路径故意改坏代码,确认测试会红
贴真实数据排错数据泄漏,无法回收用脱敏样本复现问题
让它顺手重构提交里混入无关改动明确写「本次不做的事」

小结:规格先行让「对不对」有判断依据,小步提交让「出错」可以回滚,先解释再修改让改动可理解,逐行 review 让责任落在人身上,敏感信息不外发守住底线;AI 可以写代码,但代码的责任人只能是你

笔记加载中…