
开篇
经过前 3 篇文章,task-api 已经完成了基础接口、异常处理和自动化测试。
但测试通过,只能说明已覆盖的场景没有失败。提交代码前,还需要确认:
- 有没有权限、数据和边界风险?
- 代码是否出现了不必要的重复和复杂度?
- 文档、测试和实际行为是否一致?
- Git 提交中是否混入了无关文件?
今天完成项目的最后一轮检查:
text
代码审查
↓
确定重构范围
↓
执行重构
↓
测试回归
↓
提交前检查
一、先让 AI 审查风险,不要先让它重构
我会把需求、接口契约、测试结果和本次改动范围一起交给 AI:
text
请审查 task-api 的本次代码变更,先不要修改代码。
项目约束:
- Node.js 20 + Express。
- 数据暂时保存在内存中。
- title 必须是非空字符串。
- PATCH 只允许修改 completed。
- 任务不存在返回 404 和 TASK_NOT_FOUND。
- 已有 Vitest + Supertest 测试。
请按下面顺序检查:
1. 功能正确性和边界条件。
2. 数据是否可能被非法覆盖。
3. 错误状态码和错误结构是否一致。
4. 异常是否会泄露堆栈或内部信息。
5. 是否存在明显的重复、过深嵌套或无效抽象。
6. 测试是否覆盖本次改动的关键风险。
每个问题请输出:文件位置、触发条件、影响、严重程度、建议验证方式。
没有证据的问题不要列为缺陷。
让 AI 先找问题,有助于把"真正的风险"和"个人代码偏好"区分开。
二、我会优先检查这 5 个地方
1. 输入是否经过明确校验
不能只检查字段存在,还要检查类型和内容:
javascript
if (typeof title !== "string" || title.trim() === "") {
return res.status(400).json({
error: {
code: "INVALID_TITLE",
message: "title 不能为空"
}
});
}
2. 客户端能否覆盖服务端字段
不要直接把整个请求体合并到任务对象:
javascript
Object.assign(task, req.body);
应该只更新已经允许的字段:
javascript
task.completed = req.body.completed;
3. 错误是否能被调用方区分
参数错误、资源不存在和服务器异常,应该分别使用 400、404 和 500,并返回稳定的 error.code。
4. 异常是否被吞掉
下面这种写法很难排查问题:
javascript
try {
// 业务代码
} catch (error) {
return res.status(500).json({ message: "操作失败" });
}
至少要在服务端记录错误和请求标识,同时对客户端隐藏内部堆栈。
5. 测试是否验证了真实副作用
删除接口不能只检查返回 204,还要确认任务确实从存储中消失;修改接口不能只检查请求成功,还要确认只有允许的字段发生变化。
三、哪些代码值得重构
不是所有看起来不优雅的代码都值得改。
我会使用下面三个判断条件:
| 判断问题 | 适合重构的信号 |
|---|---|
| 是否影响正确性 | 存在重复校验、字段被错误覆盖 |
| 是否增加维护成本 | 同一规则散落在多个路由 |
| 是否有测试保护 | 修改后可以用测试证明行为不变 |
例如,4 个接口都重复构造错误响应,就值得提取一个小函数:
javascript
function sendError(res, status, code, message) {
return res.status(status).json({
error: { code, message }
});
}
但如果只是为了把 3 行代码改成 1 行代码,却增加了新的抽象层,就没有明显收益。
可以记住:
重构的目标是降低未来修改成本,不是让代码看起来更"高级"。
四、让 AI 做最小重构
确认重构有必要后,再使用约束更强的 Prompt:
text
请对 task-api 做一次最小范围重构。
重构目标:
- 消除重复的错误响应构造。
- 保持所有接口路径、请求参数、状态码和响应结构不变。
- 不新增第三方依赖。
- 不修改任务存储方式。
- 不调整无关文件。
执行要求:
1. 先列出准备修改的文件。
2. 说明每个修改解决的具体问题。
3. 给出修改后的代码。
4. 列出必须重新运行的测试。
5. 如果某处没有足够收益,请明确保留原实现。
最重要的限制是"保持外部行为不变"。
如果重构同时改变了接口返回值、错误码或字段名称,那它就不再是单纯重构,需要重新走需求和接口评审流程。
五、重构后必须重新验证
建议按这个顺序执行:
bash
npm test
npm start
然后验证关键接口:
bash
curl -i http://localhost:3000/api/tasks
curl -i -X POST http://localhost:3000/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"回归测试"}'
重点关注:
- 成功状态码是否改变。
- 错误结构是否改变。
- 原有测试是否仍然通过。
- 新增的抽象是否让排查更困难。
如果重构后测试没有失败,不代表所有行为都正确;还要确认测试本身覆盖了本次修改涉及的路径。
六、提交前检查 Git 改动
代码可以运行后,再查看实际提交内容:
bash
git status --short
git diff --stat
git diff --check
git diff
我会重点确认:
text
[ ] 没有提交 .env、密钥和本地配置。
[ ] 没有混入日志、临时文件和编辑器配置。
[ ] 代码改动与当前需求有关。
[ ] 测试文件和必要文档已经包含。
[ ] 没有把调试代码、console.log 提交进去。
[ ] diff 中没有明显的格式或空白错误。
提交信息也应该说明真实改动,例如:
bash
git add src test README.md
git commit -m "feat: 完成任务清单 API 基础能力"
不要使用"update""fix bug"这类无法表达内容的提交信息。
七、Day 22 到 Day 25 的交付结果
这 4 篇文章完成了一个小项目的最小闭环:
| 阶段 | 完成内容 |
|---|---|
| Day 22 | 初始化项目并跑通第一条 API |
| Day 23 | 明确接口契约并统一异常响应 |
| Day 24 | 用测试验证边界并发现隐藏 Bug |
| Day 25 | 完成审查、重构和提交前检查 |
它还不是一个生产级服务,但已经具备继续演进的基础:需求有边界,接口有约定,代码有测试,提交有检查。
总结
AI 参与项目交付时,建议保持这个顺序:
text
先审查风险
↓
只重构有收益的部分
↓
保持外部行为不变
↓
运行测试和接口验证
↓
检查 Git diff 再提交
- 先判断问题是否真实存在,再决定是否重构。
- 高风险问题优先处理,代码风格问题不要喧宾夺主。
- 重构必须有测试保护,并且不能悄悄改变接口契约。
- 提交前检查 Git diff,避免把无关文件和敏感信息带入仓库。
这个小项目的最终价值,不是 AI 生成了多少代码,而是我们完整走了一遍从需求到交付的工程流程。
下一篇文章,我们将复盘一次真实失败案例:
《一次真实失败:AI 代码看起来没问题,为什么还是翻车了?》
✍坚持原创,求关注,点赞,收藏