用了半年 AI 编程,我总结出 5 类"别让 AI 碰"的场景

0 阅读11分钟

上个月我用 Claude Code 重构一个老项目的认证模块。AI 跑了十几分钟,改了六七个文件,代码看着挺漂亮,单元测试也全绿。我心想不错,合了代码就去吃饭了。结果当晚收到告警,线上登录全挂了。排查下来,AI 把一个自定义的 token 校验逻辑"优化"成了标准 JWT 验证,完全忽略了我们系统里那套非标的 token 刷新机制。

这件事之后我开始认真想一个问题:AI 编程的边界到底在哪?

用 AI 写代码半年多了,从一开始的"这玩意儿太猛了"到现在的"这玩意儿得管着用",我越来越觉得,知道什么时候不该用 AI,比知道怎么用 AI 更重要。下面是我踩过的 5 个坑。

太长不看版

  1. 安全相关的代码别让 AI 独立写。认证、加密、权限这些模块,必须人工把关。
  2. 架构决策别交给 AI。它擅长写函数,不擅长做系统级取舍。
  3. 老项目的深层重构要谨慎。AI 看不到隐式依赖,改一处可能崩一片。
  4. 生产环境的诡异 bug 别指望 AI 一步到位。它给的"可能原因"经常把人带沟里。
  5. 核心业务建模必须人来做。AI 可以帮你写 CRUD,但理解不了"为什么这么做"。
  6. 正确姿势不是不用 AI,而是让 AI 当执行者,你来当架构师和质检员。
  7. 一个简单判断标准:如果你自己不能 review 这段代码,就别让 AI 写它。

第一类:安全相关的代码

先说最狠的那次。

我让 Claude Code 帮一个内部系统加 RBAC 权限控制。它生成的代码结构很清晰,中间件、装饰器、角色表一应俱全。但我做 code review 的时候发现了一个问题:它在判断用户角色时用了字符串拼接来构造查询,而不是参数化查询。这在我们那个场景里不会直接导致 SQL 注入,但它暴露了一个倾向:AI 生成的代码会优先追求"能跑",而不是"安全"。

这不是个案。有研究和社区测试都给出过类似结论:AI 生成代码在安全上更容易出问题,甚至有人给出过约 1.7 倍的数字。原因也不复杂。大模型训练数据里包含了海量开源代码,这些代码本身的安全水平参差不齐。AI 学到的是"大家常怎么写",不是"这里应该怎么写"。

最该小心的几类地方,其实都很好理解:

  • 认证和授权,比如 token 校验、OAuth 流程、session 管理。AI 很容易把你的自定义逻辑替换成标准实现。
  • 加密和密钥管理。它可能选了过时算法,或者把密钥硬编码进代码里。
  • 输入校验和过滤。XSS、SQL 注入、路径遍历这些,AI 写出来的防护经常不扎实。
  • 权限边界。谁能访问什么、能改什么,这种地方一旦出错就是事故。

我现在的做法很简单:安全模块我自己写,AI 可以帮我起草测试用例,或者帮我补一些不那么敏感的外围代码。关键路径上的逻辑,还是自己来更稳。

第二类:架构层面的决策

有一次我想把一个单体应用拆成微服务,让 Claude Code 帮我规划拆分方案。它给了一个看起来很专业的方案:按业务域拆成 5 个服务,用 gRPC 通信,每个服务独立数据库。教科书级别的设计。

问题是,我们团队就三个人,运维能力几乎为零,连 Kubernetes 集群都没有。这套方案真落地了,结果就是三个人维护五套部署流程,光是服务间通信的问题就能把本来该做业务的时间吃光。

AI 做架构决策的问题,其实就一句话:它不知道你的约束条件。

它不知道你团队几个人,不知道运维水平,不知道预算,也不知道上线 deadline。它知道"最佳实践",但最佳实践放到你的上下文里,可能就是最差实践。三个人的小团队,硬塞微服务、消息队列、分布式缓存,全都上了,不叫先进,叫折腾。

而且 AI 还有个常见毛病:它偏爱流行方案。流行不等于适合你。它给你的通常是一个终态方案,不是一条从现状慢慢走过去的路径。

所以架构决策还是得人来拍板。不过 AI 在这里也不是没用。你可以让它帮你列某个方案的 pros/cons,帮你写 ADR(Architecture Decision Record),或者整理不同方案的对比表。它适合当参谋,不适合当总设计师。

第三类:老项目和大型代码库的深层改动

这类场景我吃过好几次亏,说一个印象最深的。

我们有个 Spring Boot 的订单服务,跑了四年多,从 Spring Boot 1.x 一路升上来的,中间换过三拨人。里面有个 OrderSyncService,负责把订单状态同步到下游的物流系统。代码风格很老,满屏的 @Autowired 字段注入,事务注解和业务逻辑混在一起,Service 层动辄上千行。

我让 AI 帮我重构这个类,主要是把字段注入改成构造器注入,顺便拆分一下过大的方法。AI 改完之后代码确实清爽了不少,mvn test 全绿。但上线后发现有个定时同步任务偶尔会重复执行,物流系统那边收到了重复的发货指令。

查了两天才找到原因。原来那个 Service 里有一个 private volatile boolean syncLock 字段,配合一个 synchronized 块做了简易的互斥控制,防止定时任务和手动触发同步的请求同时跑。没有注释,字段名就叫 syncLock,很容易被当成普通的状态标记。AI 重构的时候把这个类拆成了两个 Bean——OrderSyncServiceOrderSyncExecutorsyncLock 留在了 OrderSyncService 里,但实际执行同步的逻辑被挪到了 OrderSyncExecutor。两个 Bean 各持各的状态,互斥就失效了。

老项目里到处都是这种"看不见的地雷"。Spring 项目尤其多,因为 Bean 的生命周期、作用域、代理机制这些东西,很多时候代码表面上看不出来。前人为了修某个线上 bug 加的一行 @Lazy 或者一个 @DependsOn,看着像顺手写的,实际上删了就出循环依赖或者启动顺序错乱。AI 看得到字面意思,看不到代码背后的历史。

几个 Spring 老项目里 AI 特别容易踩的坑:

  • Bean 拆分破坏状态共享。AI 喜欢按"单一职责"拆类,但它不理解拆完之后原来共享的实例变量变成了两份。
  • 事务边界被改动。AI 重构方法的时候可能把一个 @Transactional 方法拆成多个私有方法调用,不知道 Spring 事务代理只作用于外部调用,内部 this.xxx() 调用事务注解不生效。
  • @Order@DependsOn@Lazy 被"清理"掉。AI 觉得这些注解"不必要",实际上它们往往是前人踩完坑之后加的。
  • MyBatis XML 映射和 Java 代码的隐式关联。你改了 Mapper 接口的方法签名,但 XML 里的 id 没跟着改,编译不报错,运行直接炸。AI 经常只改 Java 不改 XML。

我的教训是,老项目里让 AI 做局部的小改动,一次只动一个类,改完就跑完整的集成测试。特别是 Spring 项目,改完之后至少要把应用完整启动一次,光跑单元测试不够,很多 Bean 装配的问题单测发现不了。大范围重构之前,先让 AI 帮你梳理 Bean 依赖关系和调用链,你自己确认清楚了再动手。千万别让它一口气改六七个文件。

第四类:生产环境的诡异 bug

大家应该都遇到过那种"本地跑得好好的,一上线就出问题"的 bug。这类 bug 我试过交给 AI,结果基本都不理想。

有一次线上有个接口偶发性超时,大概每天出现三四次,没有明显规律。我把错误日志和代码贴给 AI,它列了一堆"可能的原因":数据库连接池不够、网络抖动、GC 停顿、锁竞争。每一条都有道理,每一条看着都像。

问题是,照着这个列表排查,每条都得花半天。我花了两天验证了前三个可能性,全部排除。最后还是靠自己加了细粒度的耗时埋点,才发现是一个第三方 SDK 在特定参数组合下会触发内部重试,重试间隔刚好卡在超时阈值上。这种问题,你不进到具体的运行时上下文里去看,光看代码基本找不到。

AI 调试的局限,说到底就是它没有"现场"。它只能看代码,看不到线程状态、内存快照、网络延迟这些运行时信息。它列出的"可能原因"往往很多,但没有优先级,不知道你的环境里到底哪个更像真凶。

更麻烦的是社区里常说的"AI 编码死亡螺旋":它改一个地方,引入一个新 bug;你再让它修,它又改出另一个问题。反复几轮之后,代码越来越乱,人也越来越烦。

我现在的做法是:调试方向自己定,让 AI 当执行工具。比如我怀疑是数据库连接的问题,就让它帮我写监控脚本;怀疑是并发问题,就让它帮我补一个压测用例。另外我给自己定了条死规矩:AI 连续两次修复都没解决问题,就立刻停下来,回退代码,自己看。

第五类:核心业务建模

这类问题可能不像前面几个那么容易炸,但长期危害最大。

我做过一个电商场景的促销系统,需求是"满减、折扣、优惠券三种可以叠加,但有优先级和互斥规则"。我把需求文档贴给 AI,它很快写出了一套促销引擎。代码质量不错,设计模式也对,用了策略模式加责任链。但有一个致命问题:它把"满减"和"折扣"的计算顺序搞反了。

先减后折和先折后减,单看一笔订单可能只差几块钱,放到整个订单量上就是大事。更关键的是,这个"顺序"不是技术问题,而是业务决策。到底先算哪个,取决于运营策略,取决于和竞品的对标,也取决于财务模型。AI 不可能知道这些。

AI 能理解"怎么实现",但理解不了"为什么要这么做"。业务建模的难点从来不在编码,而在于把业务规则准确翻译成系统行为。这一步需要和业务方反复确认边界 case,需要理解行业背景和商业逻辑,有时候还得在几个利益相关方之间做取舍。

AI 在这里最容易犯的错,是把行业里的通用做法直接当成你的业务规则。正常流程它可以写得很顺,但异常流程、回滚逻辑、并发冲突,常常想得不够。还有一种错是过度抽象:明明很简单的业务规则,它能给你包三四层,写的时候很爽,接手的人看得头大。

所以核心业务模型最好自己建。你把领域图、实体关系、核心规则先定下来,再让 AI 去写 Repository、Service、Controller 这些脚手架代码。这样它更像一个翻译器,而不是替你做业务判断的人。

一张表看清边界

场景AI 能做什么人必须做什么
安全代码起草初版、写测试用例逐行 review、确认安全约束
架构决策列 pros/cons、写方案文档结合团队和业务拍板
老项目重构局部小改、梳理调用链确认隐式依赖、控制改动范围
生产调试写监控脚本、分析日志格式定排查方向、做最终判断
业务建模将模型翻译成代码理解业务规则、设计领域模型

一条判断标准

如果你自己不能 review 这段代码,就别让 AI 写它。

AI 写的代码不一定对,但如果你有能力判断对不对,那 AI 就是在帮你省时间。如果你连对不对都判断不了,那 AI 就是在帮你挖坑。

半年前我觉得 AI 编程最重要的是怎么写好 prompt。现在回头看,更重要的是知道什么时候该自己来。

Niko-白色版.png