上个月我用 Claude Code 重构一个老项目的认证模块。AI 跑了十几分钟,改了六七个文件,代码看着挺漂亮,单元测试也全绿。我心想不错,合了代码就去吃饭了。结果当晚收到告警,线上登录全挂了。排查下来,AI 把一个自定义的 token 校验逻辑"优化"成了标准 JWT 验证,完全忽略了我们系统里那套非标的 token 刷新机制。
这件事之后我开始认真想一个问题:AI 编程的边界到底在哪?
用 AI 写代码半年多了,从一开始的"这玩意儿太猛了"到现在的"这玩意儿得管着用",我越来越觉得,知道什么时候不该用 AI,比知道怎么用 AI 更重要。下面是我踩过的 5 个坑。
太长不看版
- 安全相关的代码别让 AI 独立写。认证、加密、权限这些模块,必须人工把关。
- 架构决策别交给 AI。它擅长写函数,不擅长做系统级取舍。
- 老项目的深层重构要谨慎。AI 看不到隐式依赖,改一处可能崩一片。
- 生产环境的诡异 bug 别指望 AI 一步到位。它给的"可能原因"经常把人带沟里。
- 核心业务建模必须人来做。AI 可以帮你写 CRUD,但理解不了"为什么这么做"。
- 正确姿势不是不用 AI,而是让 AI 当执行者,你来当架构师和质检员。
- 一个简单判断标准:如果你自己不能 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——OrderSyncService 和 OrderSyncExecutor,syncLock 留在了 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。现在回头看,更重要的是知道什么时候该自己来。