如何判断 AI 生成的代码是可靠的?会从类型、测试、边界条件、性能、安全哪些维度检查?
判断 AI 生成的代码是否可靠:别只看“能跑”,要看“扛不扛打”#
一段代码的可靠性,从来不是靠“看起来挺像那么回事”来判断。
真正有分量的标准,通常只有五个字:出了事没崩。
很多 AI 生成代码,第一眼都很顺眼:
- 命名像样
- 结构工整
- 注释完整
- 主流程还能跑通
问题也恰恰出在这里。
“像代码” 和 “可靠”,中间隔着很远。
判断时,通常会按 5 个核心维度过一遍:
| 维度 | 重点看什么 | 最危险的信号 |
|---|---|---|
| 类型 | 约束是否清楚 | try?、强解包、魔法字符串满天飞 |
| 测试 | 是否真能防回归 | 只测 happy path |
| 边界条件 | 异常情况会不会碎 | 空数据、重复点击、失败回滚没处理 |
| 性能 | 主路径是否流畅 | 主线程重活、无意义重绘、任务不取消 |
| 安全 | 数据和权限是否守住 | 敏感日志、硬编码、输入不校验 |
1. 类型:代码是在表达约束,还是在逃避约束#
类型系统最重要的作用,不是“让编译通过”,而是提前限制错误的发生方式。
可靠的代码,通常会有这些特征:
- 状态清楚,互斥场景用
enum - 模型明确,不靠松散字典拼数据
- Optional 被认真处理,不靠
!硬冲过去 - 错误有语义,不是随手吞掉
- 异步代码遵守线程和 actor 语义
最该警惕的几种写法:
- 到处都是
String、Any、布尔开关 try?一路吞错,失败像没发生过if a && !b && c这种布尔组合在驱动复杂状态- UI 更新和后台任务混在一起
一句话总结:
类型越精确,运行时踩雷的概率越低。
2. 测试:不是看跑了多少,而是看挡不挡得住回归#
很多 AI 代码的问题,不是完全没有测试,而是测试只覆盖了最顺的那条路。
例如这种情况就很常见:
- 页面能打开
- 按钮能点
- 提交能成功
- 测试一片绿色
但下面这些没测:
- 空数据
- 重复提交
- 网络失败
- 本地保存失败
- 页面切走时任务取消
- 旧数据迁移
- 删除后恢复
真正有价值的测试,通常要覆盖:
- 正常路径
- 异常路径
- 空状态
- loading 状态
- 权限变化
- 并发触发
- 回归场景
还有一个很实用的判断标准:
测试是在验证“结果”,还是只是在验证“某个方法被调用过”?
如果只断言某个函数被调过一次,这类测试通常很热闹,但防不住真实问题。
可靠的测试,最好具备两个特点:
- 稳定:不靠
sleep、不靠真实网络、不靠运气 - 有针对性:改了什么风险,就测什么风险
3. 边界条件:真正拉开差距的地方#
AI 最擅长生成 happy path。
真正决定质量下限的,往往是边界条件。
一段代码是否可靠,至少要问完这些问题:
- 输入为空怎么办
- 字段缺失怎么办
- 数据损坏怎么办
- 第一次启动怎么办
- 权限被拒绝怎么办
- 用户连续点击怎么办
- 任务还没结束,页面已经退出怎么办
- 删除失败怎么办
- 磁盘写满怎么办
- 同步冲突怎么办
- 应用进后台再回来怎么办
尤其是数据类产品,边界条件不是附属问题,而是主战场。
比如日记、笔记、清单这类应用,最怕的不是界面偶尔抖一下,而是下面这些:
- 误删
- 覆盖失败
- 自动保存丢失
- 迁移损坏
- 恢复不完整
真正可靠的代码,不是“尽量别出错”,而是:
出错时也有明确行为,失败时也能被看见。
4. 性能:不卡,不等于性能没问题#
性能问题最容易被忽略,因为很多时候功能确实“能用”。
但“能用”和“顺手”中间,也隔着好几层体验差距。
常见风险点通常有这些:
- 主线程做 IO、解析、图片处理、排序
- SwiftUI 状态设计粗糙,导致整棵树反复刷新
- 列表没有稳定 identity
- 搜索输入不做节流
- 异步任务到处开,不取消
- 缓存只加不清
- 动画过重,拖慢滚动和输入
性能判断,不能只看代码长什么样,还得看运行时表现:
- 首屏是否慢
- 输入是否跟手
- 列表是否掉帧
- 页面切换是否发闷
- 后台任务是否空转
- 发热和耗电是否异常
如果是 iOS UI 改动,最稳妥的证据通常是:
- 模拟器真实交互
- 截图或录屏
- 必要时加日志或 Instruments
5. 安全:功能完成,不代表边界安全#
AI 写代码时,很容易把“跑通功能”放在第一位,然后把安全问题留在角落。
最常见的坑有这些:
- 敏感信息打印进日志
- token、路径、用户内容被硬编码或暴露
- 导出、分享、文件访问边界不清楚
- 外部输入不校验
- 错误提示暴露内部实现
- 权限申请过度,解释不足
尤其是内容类应用,下面这些都属于敏感数据:
- 文本内容
- 搜索词
- 时间信息
- 文件路径
- 导出记录
- 同步状态
真正可靠的代码,在安全上通常有两个特点:
- 默认保守,不默认放开
- 出错时不泄露不该泄露的东西
6. 最后补一刀:结构能不能撑住下一次修改#
有些 AI 代码第一次看不差,第二次改就开始崩。
问题不一定出在功能上,而是出在结构上。
典型信号包括:
- View 里塞业务逻辑
- ViewModel 里塞持久化
- Repository 里塞展示格式化
- 一个文件越来越大,什么都往里加
- 复制第三份相似逻辑,而不是抽共用部分
可靠的代码,不只是“当前能跑”,还要满足:
- 职责边界清楚
- 后续修改不容易误伤
- 问题出现时好定位
- 不会因为小改动把整个模块带乱
这部分不一定立刻炸,但一定会影响长期稳定性。
一份简单的检查清单#
看到一段 AI 生成代码时,快速扫这一遍,基本就能判断个八九不离十:
- 能否完整 build,通过后是否没有新增 warning
- 类型是否准确表达状态,而不是一堆布尔拼逻辑
- 是否存在强解包、静默失败、魔法字符串
- 是否补了针对本次改动的回归测试
- 是否覆盖异常路径和空状态
- 边界条件是否被明确处理
- 主线程是否做了不该做的事
- UI 是否可能因为状态变化被过度刷新
- 是否存在敏感日志、硬编码、输入不校验
- 文件职责是否仍然清楚,是否新增了新的大而全类型
结尾#
判断 AI 代码是否可靠,核心从来不是“像不像专业工程师写的”,而是下面这句话:
类型能不能拦错,测试能不能兜底,边界会不会碎,性能会不会掉,安全会不会漏。