LLM 写代码的新风险:不是写错,而是差一点就好
2026/6/12 16:44:14 网站建设 项目流程

AI 生成代码能跑还不够,团队更要警惕悄悄累积的过度复杂度。
原文链接:AI 小老六

工程团队对AI 写代码的警惕,常常放在明显错误上:类型不对、边界没处理、测试跑不过、API 编造。这样的错误反而好处理。编译器、测试、代码审查都会拦一遍。

更难处理的是另一类代码:它能跑,测试也过,局部看起来没什么大问题,只是比必要的实现复杂了一点。

一点点复杂度最容易被忽略。它没有严重到必须返工,也不会在发布当天炸掉。它只是静静地进入仓库,和后面几十次类似的提交叠在一起,慢慢把系统推向更难改、更难读、更难删的状态。

图:能跑的代码,也可能把维护成本悄悄带进系统。

一个 24 行函数暴露的问题

场景很普通:把用户输入的字符串转换成安全的HTTP Header值。这个处理有安全意义,不能让换行、控制字符或路径分隔符制造 Header 注入之类的问题。

AI 给出的实现大致做了几件事:

步骤处理动作目的
过滤字符移除不可打印字符避免控制字符进入 Header
替换分隔符/\换成_避免路径语义泄漏到 Header
百分号编码对非安全字符做编码兼容 RFC 5987 风格的 Header 值
十六进制补零不足两位时补0让编码字节格式统一

这套逻辑看上去很扎实,甚至有点「安全感」。每一步都有名字,每个分支都像是在防御一个潜在问题。

麻烦就在这里。

十六进制补零函数表面上合理,实际上永远不会触发。因为进入编码阶段之前,低于空格的控制字符已经被过滤掉了;能进入补零逻辑的字节,不会落到需要补零的范围。测试覆盖率工具发现了这个不可覆盖分支,问题才浮出水面。

如果没有覆盖率检查,这段代码很可能就合并了。

AI 没写烂代码,它写了略显笨重的代码

这类问题不能简单归为「AI 胡写」。恰恰相反,代码的安全意图是对的,局部封装也合理,测试还覆盖了主要边界。

真正的问题是:实现没有充分利用已有库能力,而是手写了一套更啰嗦的局部机制。人工重写后,逻辑可以压缩成更短的管道:过滤不可打印字符,替换路径分隔符,再交给成熟的 URL 编码函数处理。

图:更短的处理链路,往往意味着更少的维护负担。

图:安全相关的小轮子,常常会变成未来的维护债。

少掉的不只是几行代码。少掉的是一个永远无法覆盖的分支、一段手写编码逻辑、一处未来读代码时需要重新验证的细节。

这就是「差一点就好」的真实成本。

为什么人会接受这类代码

AI 生成的代码有一个很强的心理优势:它已经在眼前了。

需求可能很小,时间可能很紧,变更可能只是 200 行里的一个小函数。审查者看见它能跑、测试齐全、风险局部,就很容易放过。毕竟重写它需要重新组织思路,还要承担「我是不是在为风格洁癖浪费时间」的心理负担。

人类写代码也会复杂化。区别在于,AI 可以把这种复杂化稳定地、大规模地带进日常开发。一次多 8% 没什么,十次、百次之后,仓库会变成另一种样子。

AI 代码审查要多问一个问题

过去审查代码,常见问题是:

审查问题主要关注
能不能跑功能正确性
测试够不够回归风险
有没有安全洞边界与攻击面
能不能维护结构、命名、依赖

AI 时代需要再加一个问题:有没有比必要实现多出来的复杂度?

这个问题不等于追求最短代码。过度压缩同样危险。它问的是:这段复杂度有没有明确职责?有没有现成库可以替代?有没有分支永远不会发生?有没有为了显得严谨而手写了一个未来没人想维护的小系统?

图:AI 代码审查不仅要找缺陷,也要主动删掉多余复杂度。

团队可以直接加三条规则

第一,AI 生成的局部工具函数必须接受 ​删减式审查​。审查者不只看它缺什么,也要看它多了什么。

第二,遇到手写编码、解析、转义、序列化、日期处理、权限判断时,先找成熟库。安全相关代码里,自己造的小轮子通常不是勇敢,是欠账。

第三,把覆盖率失败当成设计信号,而不是单纯补测试。不可覆盖分支经常说明代码形状不对,不一定说明测试不够努力。

AI 编程已经不是「能不能用」的问题。它当然能用,而且会越来越好。更实际的问题是:我们能不能在它交出一段看似合格的代码时,仍然愿意多花五分钟,把那一点点不必要的复杂度拿掉。

这五分钟很便宜。以后再付,通常就贵了。

推荐阅读

LLM 编程提速之后,为什么你反而更难想清楚问题

AI 生成 PR 正在刷爆开源项目:GitHub 贡献信号为什么失灵了

AI 编程争论变味了:为什么反 AI 情绪开始走向怀旧化

AI 没有 ROI?企业真正暴露的,是 Token 成本失控

Claude Opus 4.8 深度解读:让 AI 模型学会承认不确定性,才是真正的生产力升级

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询