一次真实失败:AI 代码看起来没问题,为什么还是翻车了?

开篇

AI 生成的代码最危险的一类问题,不是语法错误。

语法错误会立刻报错,测试也很容易发现。真正容易翻车的是:

代码能运行,正常流程能通过,但它悄悄漏掉了一条业务规则。

这一篇复盘一个任务 API 中很典型的失败:用户可以把任务标记为完成,却无法把已完成任务恢复为未完成。

接口、代码、测试看起来都没有问题,为什么还是出了问题?

一、表面上一切正常

任务状态接口约定是:

http 复制代码
PATCH /api/tasks/:id
Content-Type: application/json

{
  "completed": true
}

AI 给出的校验代码是:

javascript 复制代码
const { completed } = req.body;

if (!completed) {
  return sendError(res, 400, "INVALID_STATUS", "completed 必须是布尔值");
}

task.completed = completed;
return res.json(task);

第一次看,这段代码似乎很合理:

  • 没有传 completed 会报错。
  • completed 为 true 可以更新任务。
  • 任务不存在时也有 404 处理。
  • 所有测试都通过了。

于是代码上线。

二、真正的故障是"无法撤销完成状态"

过了一段时间,用户需要把误完成的任务重新打开,请求是:

json 复制代码
{
  "completed": false
}

服务却返回:

json 复制代码
{
  "error": {
    "code": "INVALID_STATUS",
    "message": "completed 必须是布尔值"
  }
}

这不是接口不支持"撤销完成",而是代码把合法的 false 当成了无效值。

在 JavaScript 中,下面这些值都会被判定为假:

javascript 复制代码
false
0
""
null
undefined

所以:

javascript 复制代码
if (!completed)

检查的不是"是否为布尔值",而是"是否为真"。

这就是失败的根因。

三、为什么 AI 代码看起来没问题

这次失败通常由三个因素叠加造成。

1. Prompt 只强调了"必须是布尔值"

如果只告诉 AI:

text 复制代码
completed 必须是布尔值。

AI 可能会生成最常见的"非空校验",却没有真正检查类型。

更准确的描述应该是:

text 复制代码
completed 必须存在,且只能是 true 或 false。
false 是合法值,不能视为缺失。

输入约束越精确,AI 越不容易把语言习惯带进业务规则。

2. 测试只覆盖了 true

原测试可能是这样:

javascript 复制代码
it("可以将任务标记为完成", async () => {
  const response = await request(app)
    .patch("/api/tasks/1")
    .send({ completed: true });

  expect(response.status).toBe(200);
  expect(response.body.completed).toBe(true);
});

它证明了"可以完成",却没有证明"可以恢复"。

测试通过,只说明已测试的路径正常,不能说明接口规则被完整实现。

3. 代码审查只看了异常分支是否存在

审查时容易问:

text 复制代码
有没有参数校验?
有没有返回 400?
有没有测试?

这些问题都能得到"有"的答案。

但更应该问:

text 复制代码
合法值的完整集合是什么?
每一个合法值都测试了吗?
false、0、空字符串在当前语言里会不会被混淆?

四、正确的修复方式

对于明确要求布尔值的字段,应该检查类型:

javascript 复制代码
const { completed } = req.body;

if (typeof completed !== "boolean") {
  return sendError(res, 400, "INVALID_STATUS", "completed 必须是布尔值");
}

task.completed = completed;
return res.json(task);

这样结果才符合契约:

请求值 结果
true 合法,更新任务
false 合法,更新任务
"false" 非法,返回 400
0 非法,返回 400
未传字段 非法,返回 400

修复代码只有一行变化,但前提是先识别出错误的业务边界。

五、把线上问题变成回归测试

修复后,至少要补上这两组测试:

javascript 复制代码
it("可以把未完成任务标记为完成", async () => {
  const response = await request(app)
    .patch("/api/tasks/1")
    .send({ completed: true });

  expect(response.status).toBe(200);
  expect(response.body.completed).toBe(true);
});

it("可以把已完成任务恢复为未完成", async () => {
  const response = await request(app)
    .patch("/api/tasks/1")
    .send({ completed: false });

  expect(response.status).toBe(200);
  expect(response.body.completed).toBe(false);
});

再补充非法输入:

javascript 复制代码
it.each([undefined, null, 0, "false"])(
  "completed 为 %p 时返回 400",
  async (completed) => {
    const response = await request(app)
      .patch("/api/tasks/1")
      .send({ completed });

    expect(response.status).toBe(400);
    expect(response.body.error.code).toBe("INVALID_STATUS");
  }
);

这组测试不追求数量,而是把"能完成"和"能撤销"这两个业务状态都固定下来。

六、如何让 AI 帮你做这类复盘

故障出现后,不要只问 AI:

text 复制代码
这段代码有什么问题?

可以这样提供上下文:

text 复制代码
请复盘下面的接口故障,先不要修改代码。

接口规则:
- PATCH /api/tasks/:id 只允许修改 completed。
- completed 必须是布尔值。
- true 和 false 都是合法业务状态。

实际故障:
- 请求 { "completed": true } 成功。
- 请求 { "completed": false } 返回 400。

请输出:
1. 已确认事实。
2. 最可能的根因。
3. 需要检查的 JavaScript 语义风险。
4. 最小修复方案。
5. 必须补充的回归测试。
6. 如何修改需求说明和 Prompt,避免再次发生。

这个 Prompt 的重点是明确"false 合法"。否则 AI 也可能重复给出错误的非空校验。

七、从这次失败学到的 4 件事

text 复制代码
[ ] 正常流程通过,不等于所有合法状态都支持。
[ ] 语言中的真假值,不能替代业务规则校验。
[ ] 测试要覆盖值域,不只是覆盖成功和失败。
[ ] AI 输出中的简洁判断,尤其需要检查边界含义。

以后看到下面这些写法时,建议多看一眼:

javascript 复制代码
if (!value)
if (value)
value || defaultValue

它们在处理字符串、数字、布尔值时,可能会把"合法的假值"误判成"缺失值"。

总结

这次翻车不是 AI 不会写代码,而是我们把一个精确的业务规则,交给了一个模糊的校验实现。

正确的复盘顺序是:

text 复制代码
还原真实请求
  ↓
确认业务规则
  ↓
定位语言语义差异
  ↓
最小修复
  ↓
补充回归测试
  ↓
更新 Prompt 和接口契约
  • AI 代码"看起来合理",不代表它符合所有业务状态。
  • 布尔值、空值、零值等边界,需要明确写进需求和测试。
  • 每一次线上故障,都应该沉淀成可重复执行的测试。
  • 开发者的价值,在于确认规则、识别风险并验收结果。

下一篇文章,我们将继续讨论一个更重要的边界:

《哪些任务该交给 AI,哪些必须由开发者负责?》


✍坚持原创,求关注,点赞,收藏

相关推荐
李航19831 小时前
AI定制柜建模,需要详细的建模规范和标准流程
人工智能·python·计算机视觉·ai·ai编程
山岚的运维笔记2 小时前
ComfyUI NVIDIA安装教程:官方便携版下载+run_nvidia_gpu.bat启动,8G显存Windows实操
运维·服务器·windows·笔记·prompt·aigc·comfyui
长弓三石3 小时前
用纯 Java 做一个企业级 Agent Harness 平台:BizBuddy 的设计与取舍
开源·agent·ai编程
用户685939835385 小时前
Codex CLI 接入 OpenAI 兼容接口:config.toml 逐行讲解与常见报错排查(2026)
openai
zhangfeng11335 小时前
Ag / Cu / Au / Ru / Ir / Rh银 铜 金 钌铱 铑 纳米尺度下的 导电性 + 扩散/迁移缺点
人工智能·华为·ai编程·npu
蒸蒸yyyyzwd6 小时前
CUDA 学习笔记
ai编程
Web3_Basketball7 小时前
Ollama本地函数调用发布72小时,我替你试完了
ai编程
9i编程7 小时前
1. 教 AI 上班:带出我的数字同事 —— 把开发习惯交给 Qoder,从零搭脚手架
人工智能·openai·ai编程