AI 生成的代码为什么会“看着对,其实错”

使用 AI 写代码时,我们经常会遇到一种情况:

  • 代码格式很完整。
  • 变量命名看起来很规范。
  • 没有明显的语法错误。
  • 运行简单示例也能得到结果。

但是,放到真实项目中却出现了问题。

这就是"看着对,其实错"。

问题不一定是 AI 不会写代码,而是 AI 给出的代码通常基于已有信息进行推测。如果需求、项目上下文或验证过程不完整,代码就可能与真实目标不一致。

这篇文章重点解决一个问题:

AI 生成代码后,我们应该如何判断它到底能不能用?

一、能运行不代表正确

代码的正确性至少包含四个层面:

检查层面 需要确认的问题
语法 代码能不能被正确解析
运行 执行时会不会报错
逻辑 结果是否符合业务规则
工程 是否安全、可维护、不会影响其他功能

很多人只检查了前两项:代码没有语法错误,也可以正常运行。

但真正容易出问题的,往往是后两项。

例如,一个计算折扣的函数,即使能够正常返回数字,也不代表折扣计算一定正确。

二、AI 为什么会生成"看着对"的代码

1. 缺少业务上下文

同一个字段,在不同项目中可能有不同含义。

例如,discount 可能表示:

  • 0.2,代表打八折。
  • 20,代表优惠 20%。
  • 2000,代表优惠金额 2000 元。

如果只告诉 AI"写一个计算折扣的函数",它无法确定这个字段的真实含义,只能按照常见写法进行猜测。

2. 使用了看似合理的 API

AI 可能会生成一个名称合理的函数,或者使用一个已经过时的 API。

代码看起来符合某个框架的风格,但当前项目版本可能并不支持它。

因此,看到 AI 使用陌生方法时,应该通过项目文档、类型定义或官方文档进行确认。

3. 忽略了边界条件

AI 生成的代码通常先满足正常输入。

但真实项目还需要考虑:

  • 空值。
  • 负数。
  • 0。
  • 最大值和最小值。
  • 小数精度。
  • 错误类型。
  • 重复操作。
  • 网络或数据库异常。

如果没有明确提出这些要求,AI 可能不会主动完整处理。

4. 把示例代码误当成生产代码

为了说明思路,AI 有时会省略:

  • 参数校验。
  • 权限检查。
  • 日志处理。
  • 错误处理。
  • 超时和重试。
  • 数据库事务。

示例代码适合帮助我们理解方向,但不能直接等同于可以上线的代码。

三、一个典型的错误案例

假设业务需求是:

  • 商品价格以元为单位。
  • discount 传入整数百分比。
  • discount: 20 表示优惠 20%。
  • 折后价格不能小于 0。
  • 价格结果保留两位小数。

我们让 AI 生成函数:

javascript 复制代码
function calculateFinalPrice(price, discount) {
  return price * (1 - discount);
}

这段代码看起来很简洁,但执行下面的代码:

javascript 复制代码
console.log(calculateFinalPrice(100, 20));

结果是:

text 复制代码
-1900

原因是代码把 20 当成了 20.0,而不是 20%

正确的计算方式应该先将百分比转换成小数:

javascript 复制代码
function calculateFinalPrice(price, discount) {
  if (!Number.isFinite(price) || price < 0) {
    throw new Error('price 必须是大于等于 0 的数字');
  }

  if (!Number.isFinite(discount) || discount < 0 || discount > 100) {
    throw new Error('discount 必须是 0 到 100 之间的数字');
  }

  const finalPrice = price * (1 - discount / 100);

  return Number(finalPrice.toFixed(2));
}

这段代码仍然需要根据项目实际规则进行确认,但至少处理了几个关键问题:

  • 明确 discount 的单位是百分比。
  • 检查价格和折扣是否为有效数字。
  • 防止折扣小于 0 或大于 100。
  • 对金额结果进行精度处理。

这个例子说明:

AI 不一定写错了语法,但可能理解错了字段含义。

四、生成代码后先检查什么

第一步:重新阅读需求

不要拿到代码后马上运行,先对照需求检查:

  • 输入参数的类型是否正确。
  • 字段单位是否正确。
  • 返回值是否符合约定。
  • 成功条件是否完整。
  • 失败时应该如何处理。
  • 是否包含权限和安全要求。

尤其要关注金额、时间、比例、状态值和 ID 这类容易产生歧义的字段。

第二步:找出 AI 做的假设

可以直接问 AI:

text 复制代码
请列出你生成这段代码时做出的所有假设。

重点检查:
1. 每个参数的类型和单位
2. 空值和异常值的处理方式
3. 时间、金额和比例的计算规则
4. 依赖的库和版本
5. 权限和安全前提

不要修改代码,只列出假设和可能需要确认的问题。

这一步很有用,因为隐藏的假设往往就是错误的来源。

第三步:准备最小测试集

至少准备四类输入:

测试类型 示例 目的
正常值 价格 100,折扣 20 检查主要流程
边界值 折扣 0、100 检查最小和最大范围
异常值 空值、字符串、负数 检查参数校验
极端值 很大的价格和小数 检查精度和稳定性

对应到前面的函数,可以先写出测试:

javascript 复制代码
console.log(calculateFinalPrice(100, 20));
console.log(calculateFinalPrice(100, 0));
console.log(calculateFinalPrice(100, 100));

try {
  calculateFinalPrice(100, 120);
} catch (error) {
  console.log(error.message);
}

预期结果应该是:

text 复制代码
80
100
0
discount 必须是 0 到 100 之间的数字

测试不是为了证明 AI 一定正确,而是为了尽快暴露错误。

第四步:检查项目环境

代码从单独示例放进项目后,还要确认:

  • 使用的库是否已经安装。
  • 导入方式是否符合当前版本。
  • 项目是否使用 TypeScript 类型约束。
  • 返回格式是否符合现有接口。
  • 日志和错误处理是否符合项目规范。
  • 是否需要补充单元测试。

如果 AI 使用了项目中不存在的函数或依赖,不能为了让代码运行就随意安装新包。先确认项目是否已经有同类能力。

五、四种常见错误要重点防范

1. 逻辑正确,业务错误

代码按照某种逻辑运行,但不符合产品规则。

例如:

  • 把自然日当成工作日计算。
  • 把"优惠 20%"理解成"价格乘以 20%"。
  • 把订单状态 1 当成已完成,但项目中 1 表示待支付。
  • 把用户的本地时间当成服务器时间。

这类问题只能通过需求、接口文档和业务示例确认,不能只看语法。

2. 正常数据正确,异常数据出错

例如搜索功能在输入关键字时正常,但输入空字符串、特殊字符或超长字符串时发生异常。

需要主动测试:

  • 空字符串。
  • 只有空格的字符串。
  • 特殊字符。
  • 超长内容。
  • 不符合类型的参数。

3. 本地可用,项目中不可用

常见原因包括:

  • AI 使用了错误的框架版本。
  • 本地示例依赖了未安装的包。
  • 环境变量名称不一致。
  • 接口字段与项目约定不同。
  • 没有考虑真实的异步和权限流程。

因此,生成代码后必须放回真实项目运行,而不是只在独立代码片段中测试。

4. 功能正确,但存在安全问题

代码能实现功能,不代表可以安全使用。

需要重点检查:

  • 是否直接拼接 SQL。
  • 是否把用户输入插入 HTML。
  • 是否绕过权限校验。
  • 是否返回密码、Token 等敏感字段。
  • 是否把详细服务器错误返回给用户。
  • 是否将密钥写死在源代码中。

安全检查应该单独进行,不要默认"功能测试通过就安全"。

六、让 AI 帮你验证,而不是只让它生成

可以使用下面这个 Prompt:

text 复制代码
请不要直接修改下面的代码,先帮我验证它是否符合需求。

需求:
[粘贴完整需求和业务规则]

代码:
[粘贴代码]

请按照以下顺序输出:
1. 代码当前实现了什么
2. 代码做了哪些未经确认的假设
3. 与需求不一致的地方
4. 需要测试的正常、边界和异常场景
5. 可能的安全风险
6. 仍然无法确定的问题

请为每个问题标注:高、中或低优先级。
只有在我确认问题后,再给出修改方案。

七、不要只看 AI 的解释

AI 解释代码时可能非常流畅,但流畅不等于准确。

验证答案时,建议结合以下方式:

  • 运行最小示例。
  • 查看项目类型定义。
  • 阅读依赖库官方文档。
  • 搜索项目中已有的同类写法。
  • 添加正常、边界和异常测试。
  • 使用代码审查工具检查修改范围。
  • 涉及核心逻辑时让同事进行人工评审。

对于金额、权限、支付、数据删除和隐私相关代码,验证标准应该更严格。

八、AI 生成代码验收清单

提交代码前,可以使用下面这份清单:

  • 我能用自己的话解释这段代码。
  • 参数类型、单位和取值范围已经确认。
  • 正常输入已经测试。
  • 边界输入已经测试。
  • 异常输入已经测试。
  • 依赖和 API 与当前项目版本一致。
  • 返回结果符合接口约定。
  • 没有遗漏权限和安全校验。
  • 没有把示例代码中的假数据带进生产环境。
  • 已经运行项目现有测试。
  • 已经检查本次修改的文件范围。
  • 我知道这段代码为什么这样实现,而不是只知道它能运行。

如果最后一项无法确认,说明这段代码还不适合直接提交。

总结

AI 生成的代码之所以会"看着对,其实错",常见原因有:

  • 业务上下文不足。
  • 参数和字段含义存在歧义。
  • 使用了过时或不存在的 API。
  • 忽略边界条件和异常处理。
  • 把示例代码直接当成生产代码。

使用 AI 编程时,不要只问"代码能不能运行",还要继续确认:

它是否符合需求?是否覆盖边界?是否适合当前项目?是否安全?

可以记住一套简单流程:

text 复制代码
先读需求
  ↓
确认假设
  ↓
运行最小示例
  ↓
测试边界和异常
  ↓
检查项目环境与安全
  ↓
再提交代码

AI 负责提高编码速度,开发者负责验证结果是否真实可靠。

下一篇文章将介绍:

《从零搭建你的 AI 编程工作流》


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

相关推荐
潘锦15 分钟前
AI 时代,让自己慢下来
ai编程
小磊哥er1 小时前
深入解构Claude Code - 第 5 篇 · 每次提问都给 AI 塞了什么资料
javascript·ai编程
小磊哥er1 小时前
深入解构Claude Code - 第 4 篇 · 工具:AI 的手
javascript·ai编程
AI创界者2 小时前
【开源硬核】comfyUI MiniMax H3 融合模型本地部署一键整合包!单卡撬动 2K 影音全模态输出,附避坑指南
人工智能·aigc
coft2 小时前
Pi Agent 架构与关键功能全解析
ai·ai编程
AI智图坊2 小时前
甩手图省事的技术原理:如何用“商品锁定”机制解决AI作图的一致性难题
大数据·人工智能·计算机视觉·ai作画·aigc·ai写作
小磊哥er2 小时前
深入解构Claude Code - 第 3 篇 · 一问一答怎么转起来
javascript·ai编程
小磊哥er3 小时前
深入解构Claude Code - 第 2 篇 · 启动的秘密
javascript·ai编程
Rolei_zl3 小时前
AIGC(生成式AI)试用 57 -- 向量数据库
aigc·向量数据库