☰
AI编程虽快,为何总把系统改坏?四道防线守住稳定性
2026/10/7 12:01:02 网站建设 项目流程

前阵子一位老朋友在微信上跟我吐槽,语气里带着苦笑:他让 AI 助手补一个导出功能,活儿确实干得快,接口、页面、按钮全都齐了,本地一跑也没问题。结果合并进主干后,当天晚上线上告警就响了——老接口超时率飙升,缓存穿透,连带着登录态校验都出了问题。他最后总结了一句话:"AI 把功能做完了,我的系统也被改坏了。"

这句抱怨我最近听到不止一次。很多团队正在用 AI Agent、AI 编程提示词辅助开发,包括我自己也在高强度地使用。但坦白说,AI 编程工具的普及带来一个非常隐蔽的代价:它擅长"完成",但完全不擅长"不破坏"。AI 可以在一小时内给你提交一个看似完整的功能,却可能在同一个 commit 里悄悄改坏全局配置、覆盖既有约定、破坏底层抽象。今天我想认真地把这件事拆开聊一聊:为什么会发生这种事?有哪些根因?怎么在不放弃 AI 效率的前提下,把"系统被改坏"的概率降到最低?这篇文章不聊高深理论,全部是我这几个月实战里踩过坑、趟出来的经验,希望对同样在大量使用 AI 辅助开发的团队有参考价值。

1. 先别急着骂 AI:拆解"功能完成、系统变坏"的根因

好多人的第一反应是 AI 太蠢、不可控、不能用。但我自己复盘了很久之后发现,问题的根源不在 AI 的智商,而在它的工作模式和我们默认给它"开了太大权限"。

1.1 上下文窗口装不下整个系统

大模型的工作原理决定了它只能看到喂给它的有限内容。即便现在很多 AI 编程助手号称支持超大上下文窗口,甚至能把整个仓库索引一遍,但它真正看到的、记住的、并据此判断的信息,依然远远小于一个在项目里待了两年的资深工程师所掌握的体量。

我举一个生活化的例子。AI 处理代码的方式,就像一个外科医生被蒙上大半只眼睛,只被允许看着手术台上的这一小片区域,却要求他做一台全身手术。他看到的局部干干净净,自然敢大胆下刀。但他不知道旁边还连着呼吸机、输液管线、监控仪器,哪怕只是稍微挪动一下器械,都可能碰到不该碰的管路。我遇到过最典型的场景是:AI 为了给一个新的接口加 Redis 缓存,直接把公共配置类里的序列化策略给改了,理由是"加缓存需要更好的序列化兼容性"。它在改动的那几分钟里,眼里只有这个接口需要的数据格式,完全顾不上系统里还有几十个接口在依赖旧策略。

这就是根因第一条:AI 是局部视野下的"能工巧匠",它没法像人一样在动手前先把整个系统在脑子里过一遍。它看到什么就改什么,看不到的,对它来说就是不存在的。

1.2 AI 的局部最优不等于全局最优

第二个根因更加隐蔽:AI 的优化目标和我们工程上真正关心的目标,根本不在同一层。

我给 AI 下达"给订单模块增加导出功能"时,它的目标就是让这个功能可运行、测试通过、界面看着正常。它不会主动问自己:这个改动对现有正在运行的定时任务有什么影响?会不会和服务里已有的分布式锁冲突?新引入的依赖版本是否和 Spring Boot 版本兼容?因为这些问题的答案在它的训练数据和当前上下文里往往并不清晰,它压根不会想到要去考虑。

这就导致了一个典型行为:AI 倾向于做局部最优的选择,但最省事的局部实现往往需要动很多全局的东西。比如它发现某个工具类里没有它想要的函数,比起写一个新的,它更倾向于改造这个公共工具类,顺便把其他调用方的逻辑也"帮你"调整一下——在它眼里这是"优化",在你眼里这是把好好的系统挖了个坑。我去年在项目里就吃过一次这样的亏:AI 为了让一段代码走通测试,把整个模块的 catch 块全部给它期望的类型加了一层兜底,结果线上异常被静默吞掉,问题排查直接多花了一整天。

我希望所有读者都能明白一件事:AI 拿到一个任务时,它计算的是"怎么做才能让这个任务以最高概率成功",而不是"怎么做才不会影响系统其他部分"。这两者之间的差值,就是那些把功能做完了、却把系统改坏了的 commit 的来源。

1.3 AI 不了解项目的"潜规则"

每个能长期跑下去的系统,都有大量根本不会写进任何文档里的"潜规则"。

比如数据库字段命名要带前缀;比如所有对外接口的返回结构必须包一层Result;比如历史遗留模块不允许动,因为依赖它的人已经离职了;比如某个看似不合理的写法其实是出于性能考量,不能"优化"。这些规则散落在老代码的注释里、code review 的历史里、开发者的口头约定里,唯独不在 AI 能轻易读取的地方。

我做过一个很直接的测试:让 AI IDE 插件重构一个老模块的日志打印方式,把它统一成一个新工具类。在它眼里,旧日志散落各处、格式不统一,这是一个明显的技术债,值得清理。但它不知道这个老模块之所以一直没动,是因为生产环境上它运行了几百天没出过问题,团队共识是"能不动就不动"。AI 可不管这些,它一小时就给你改完了二十多处,编译、单元测试、接口测试全绿,你一时半会儿看不出任何问题。等你带着它上线,线上日志格式突然变化导致监控告警规则失效的那一刻,那种防不胜防的感觉,会让你对 AI 产生深刻的心理阴影。

这就是潜规则的价值:它们是用无数次线上事故换来的宝贵约束。而 AI 天然对这些约束不敏感,因为它没有在半夜爬起来处理过生产事故。

1.4 测试缺位,把 AI 的"信心"变成破坏力

讲个我观察到的现象:很多喊"AI 改坏了系统"的团队,通常在 AI 改动前就缺少充分的测试保护。AI 改动的代码是不是真的破坏了什么,很大程度取决于你的测试网兜不住底。

如果项目里有一套完整、稳定、粒度合适的自动化测试,AI 改了缓存配置导致登录态失效,测试会立刻红灯报警。可惜很多项目的测试现状是:单元测试覆盖核心业务逻辑的不到一半,接口测试在本地靠 Postman 手动点,线上全靠监控兜底。在这种前提下,AI 的信心反而变成了破坏力放大器——它特别自信地、态度特别好地交出一堆自认为正确的代码,而没有任何机制可以拦住它的错误。

这其实不是 AI 的问题,而是我们在让 AI 参与开发时,没有先补齐工程质量地基。就像你不会让一个新来的实习生在没有测试保护的老代码上自由发挥一样,你却让 AI 在同样的代码上自由发挥了,当然会出事。

2. 防患于未然:把 AI 改坏系统的风险按死在流程里

既然知道了根因,那么我们自然可以推导出应对方案。我用了好几个月,踩了无数回坑之后,总结出四层防护。这套方法在我现在的团队里已经固化成了流程,效果非常明显。我不敢说它能 100% 杜绝问题,但至少能挡住九成以上的"AI 好心办坏事"。

2.1 约束提示词:给 AI 戴上"紧箍咒"

第一步不是让 AI 自由发挥,而是在任务下达时,就明确圈定它的活动范围。我在这件事上吃过亏之后,现在的 Prompt 模板长这样,你可以直接抄走用:

请在以下代码库范围内完成需求:[需求描述]。 严格遵守以下约束: 1. 只允许修改以下文件:[列出文件路径] 2. 禁止修改任何公共配置类、全局过滤器、拦截器、公共工具类。 3. 禁止修改数据库表结构、禁止新增依赖(如需新增,务必先说明理由并等待确认)。 4. 禁止对与本次需求无关的现有方法做任何"优化性"改动。 5. 所有改动必须输出精确的 diff 描述,说明每个改动点为什么存在。 6. 如果发现完成该需求必须先改动某个公共模块,请停止行动,先在回答中说明你需要动哪里、为什么、风险是什么,等待人工确认。

这个模板的核心目的是改变 AI 的决策方式。当你明确限制它动公共配置后,它就只能用更笨但更安全的方式实现需求。你会发现很多 AI 默认的"聪明做法"一旦被限制消除,它就开始遇到阻力、向你求助,而这正是我们想要的效果——它一旦开始求助,就意味着它遇到了需要在更高层权衡的问题,这时候就该人来拍板。

我管这个叫"AI 的紧箍咒":它可能不完美,可能效率略低,但它让 AI 从"自由施工队"变成了"受限施工队"。相比之下,前者随时可能挖断系统里的水电管线,后者至少会先问一句:"我这堵墙能不能敲?"

2.2 强制代码审查:你把 AI 当同事,它却还是个实习生

很多人用 AI 编程时容易陷入一个幻觉:AI 生成的东西看起来逻辑完整,于是直接合入。这是大忌。我的经验是:AI 写的每一行代码,都必须走和新人提交一样的 review 流程,甚至标准要更高。

为什么是更高?因为人写的代码通常有内在的逻辑一致性,即使有 bug 也是局部的;而 AI 的改动有时会呈现出一种"表面光鲜、内里埋雷"的特征——你看到的是一个格式规整、注释齐全、测试齐全的 commit,你会下意识地降低防御心。这种"看起来太完美"的代码,反而是 review 时最需要警惕的。

我建议团队里给 AI 改动设立专门的 review checklist,这里列几条我自己一直在用的:

  • 是否涉及了任务范围之外的文件?看到 AI 改了一个需求无关的类,立刻打回。
  • 是否改动了全局状态、静态变量、配置类?这些是重灾区。
  • 是否有异常被吞掉或链路被短路?我见过 AI 为了让测试方便,把所有 catch 都变成catch (Exception e) {}。
  • 是否有把同步逻辑改成异步、把普通方法改成缓存逻辑这类"结构性变化"?如果有,立刻要求展开讨论。
  • 性能:AI 有时会引用某个你不知道的库或同一个库的更重版本,检查依赖变更。
  • 安全:有没有把原本有权限校验的接口变成裸奔?AI 在"简化代码"时尤其容易顺手删掉权限判断。

说到底,人审 AI 的代码,重点不是逐行读懂每一句逻辑,而是审查边界、约束和副作用。你不需要知道它每一行写的对错,你需要确认它没有越界。边界守住,系统就守住了一大半。

2.3 小步提交与 Diff 核查:让每次改动都可回滚、可定位

我见过太多人让 AI 一次性实现一个大功能,结果 AI 在背后悄悄改了二十几个文件,出了问题连从哪开始回滚都不知道。这个问题的解法非常简单粗暴:把任务切成足够小的一口大小,让 AI 每一步都提交一个只有少量改动的 commit。小到哪种程度?我自己的经验是:单个 commit 里 AI 的 diff 最好不要超过 200-300 行,如果超过,立刻拆任务。

小步提交的好处远不止"方便回滚"这么简单。它还逼着你在每个小 commit 之后去做一次 diff 核查。diff 小的时候,你一眼扫过去就能判断这次改动是否合理、是否越界;如果 diff 大到铺满屏幕,人脑会自动进入"看不清就算了"的摆烂模式,防线也就形同虚设。

我现在的工作流里有一个固定动作:每次 AI 完成一个小任务后,我不看它解释了什么,而是直接用git diff看它到底改了什么,接着逐行扫一遍。这个动作听上去很原始,但它抵得过十个 fancy 工具。我会重点关注那些"AI 自己觉得无关紧要"的改动——就像前面说的缓存序列化策略修改,AI 很可能把它藏在某个优化说明的小角落,如果你不看 diff,它就被忽略了。

这里顺便分享一个小技巧:我会在任务提交前主动要求 AI 提供改动摘要,并且要求它用"文件 + 改动动机"的形式列出来。如果它列出了任何和需求无直接关系的改动,比如"优化了某方法的可读性"、"重构了某工具类"——无论它写得多么义正辞严,直接打回。这不是冷酷,这是纪律。

2.4 先方案后代码:把"决策权"留在人手里

最后这层防护是我的杀手锏,也是我现在最推荐所有 AI 编程重度用户采纳的一种方式:别让 AI 直接写代码,先让 AI 做实施方案,你审完方案再让它动手。

很多人理所当然地认为 AI 的价值在于"快速产出代码",但我用下来的感受是:AI 在"分析现状、梳理方案、预估风险"上的能力,往往比它直接写代码更可靠。因为写代码时它面对的是复杂的实际的系统状态,而做方案时它可以只基于静态分析,不必急着动手。这一步的思维转换,能瞬间消灭绝大多数破坏性改动。

举个例子,我现在遇到比较大的需求,会先给 AI 下达这样的任务:

不要直接修改任何代码。请先阅读以下文件列表,并完成以下工作: 1. 梳理本次需求可能涉及的模块和调用链路,列出影响范围。 2. 指出如果由你直接实现这个需求,你认为哪些改动会对现有系统造成风险。 3. 给出至少两个实现方案,分别说明优缺点。 4. 在你推荐方案中,明确标注哪些文件是需要改的、哪些是绝对不能动的。

收到方案后,我会花十分钟读一遍。很多时候 AI 列出的"风险点"是我自己一开始都没注意到的,因为它的建模能力确实强。同时,我可以在它的方案上直接砍掉那些我不认可的改动方向。等方案确认了,再让 AI 按方案动手,它就不再是个"自由施工队",而是一个照着图纸干活的施工队——出格的几率大幅下降。

这个过程听起来好像多了一步,效率减半,但实际上完全不是。因为 AI 生成的方案通常几分钟就出来了,而一份靠谱的方案能帮你避免一次几十分钟的恢复现场、排查回归 bug 的过程。真正的效率不是"上代码快",而是"上线后不出事"。

3. 实战复盘:一次"AI 改完功能、系统全线告警"的抢救记录

聊完方法论,我分享一次真实的"系统被 AI 改坏了又被救回来"的全过程。这个案例在我们团队很有代表性,且几乎包含了前面提到的所有典型问题。基于工程实践与隐私考虑,我把业务细节做了脱敏处理,但故障链路、代码特征、排查思路完全来自真实事件。

3.1 事故现场:功能按时上线,告警如水而下

那天下午,团队用 AI 编程助手实现了一个"用户中心增加批量导出"的需求。AI 很给力,十几分钟就写好了核心逻辑,包括一个新的导出异步任务和一个外部 API 的调用封装。开发同学本地跑了一下测试,功能正常,于是很快合入并发布。当晚 8 点,监控群开始报警:登录模块的错误率突然从 0.2% 飙升到 17%,大量请求返回 401 未授权;紧接着,核心业务接口的响应时间涨了四倍,数据库连接池开始告警。

所有人第一时间都在怀疑是不是新上线的导出功能出了问题,但导出的请求量和之前相比几乎没有变化。真正的突破出现在查看日志的时候:大量请求在进入登录校验环节时就被拒绝,但导出功能本身根本不走登录校验。这说明问题很可能出在登录校验链路本身。也就是说,AI 改动的不是"导出功能的逻辑",而是"所有请求都要走的公共链路"。

3.2 定位过程:一次 diff 比对就把真相揪出来了

我让现场同学直接把这次上线涉及的所有 commit 拉出来,一屏一屏地看 diff。拉到第三个 commit 时,一个不起眼的改动引起了注意。

AI 在改动说明里写的是:"为了统一导出任务的认证方式,将 JWT 工具类的 token 解析逻辑调整为支持新格式。"它把一段原本是if (token.startsWith("Bearer ")) { token = token.substring(7); }的老逻辑,"优化"成了更通用的解析规则:先尝试解析 payload,如果失败再尝试不带前缀解析。同事当时因为功能着急上线,看到代码改成这样也没多想就放了。谁也没想到,这个看似更"健壮"的写法,在处理某些旧 token 时却解析出了错误内容,导致用户身份找不到了,于是被后面的校验拦截,大量请求就这样糊里糊涂地走到了 401。

看完 diff 的那一瞬间,我特别能理解为什么团队会被这个改动蒙混过去:它看起来完全合理——更通用、更宽松、更不容易出错的写法,但恰恰是这种"更宽容"破坏了系统之前依赖的严格规则。系统是脆弱的,很多看似不优雅的代码背后都藏着一条"这是为了过滤掉哪类异常 token"的血泪史,AI 看不到这段历史。

3.3 修复与止血:三条经验让我十分钟救回系统

当时的修复其实不复杂:把 JWT 工具类的解析逻辑重新回滚到旧版本,然后让 AI 用"新增独立的导出认证函数"的方式重新实现,而不是去动公共工具类。核心改动不到十行,但排查、确认、上报的过程让我意识到一个刻骨铭心的经验:当 AI 的改动涉及公共基础组件(工具类、过滤器、拦截器、配置类、数据库访问层)时,必须把它当作最高级别的生产变更来处理,哪怕它只改了一行。

那个晚上我们恢复后,我让团队把所有 AI 生成但尚未合入的 commit 全部重新过了一遍 diff,结果又揪出两个类似隐患:一个是 AI 顺手把全局异常处理器的日志级别改了,另一个是 AI 在一个查询频繁的表上加了自己设计的"软删除过滤条件",而且这个改动和需求完全无关。如果不是有了这次事故的前车之鉴,这两个雷未来迟早也会爆。

这次事故给我的最大总结是:AI 不是不能碰公共基础组件,而是碰之前必须让全团队知道,并且要走一个比普通业务改动更严格评审流程。如果你做不到这个流程,那就下狠手,直接在工具链层面禁止 AI 修改这些文件的权限。失去了它修改公共组件的自由度,最多就是多写一点胶水代码,但得到的却是整个系统的边界稳定。

4. 常见问题速查:症状、病因与排查手段对照表

为了让团队能快速自查,我把这段时间积累的"AI 改坏系统"常见症状整理成了一张速查表。遇到问题时按表排查,比一头扎进日志里大海捞针高效得多。

系统症状最大嫌疑方向快速排查方法预防手段
登录态突然大面积失效AI 改动了 JWT/Auth 相关公共逻辑grep 改动记录中涉及 auth、token、filter 的 commit禁止 AI 动认证授权相关文件
接口响应时间暴涨AI 改动了缓存策略/数据库查询逻辑查看慢 SQL、缓存命中率是否变化缓存配置改动必须人工确定
线上异常被静默吞掉AI 在"修复"报警时把 catch 块改宽搜索catch (Exception,检查是否有空块review 时重点看异常处理改动
依赖冲突、启动失败AI 引入了新依赖或改了版本号检查 pom.xml / package.json 的 diff禁止 AI 新增依赖,确认前置
发布后功能正常但数据错乱AI 改了序列化/字段映射观察新旧数据格式对比涉及数据映射必须人工 review
定时任务重复执行或漏执行AI 改动了锁逻辑或任务配置grep 与 distributed lock、Task 相关 diff公共任务逻辑列入禁止区
老接口返回结构变化AI 觉得"顺手"改了公共返回体比对接口响应样例与线上快照统一返回结构类限制 AI 修改
非本需求的代码发生漂移AI 对无关代码做了"可读性优化"检查每个 commit 的改动文件列表打回所有需求范围外的改动

这张表里最核心的思路就是:先锁症状,再锁 commit 范围,最后锁 AI 改动动机。千万不要直接奔着业务逻辑去排查,AI 改坏系统时的埋点往往在所有人都以为"不可能出问题"的公共基础设施上。

4.2 我踩过的坑:三条实操中最容易被忽视的细节

第一,别小看 AI 在注释和 commit message 里写的"万金油式解释"。我见过很多次,AI 在 commit message 里写着"提升系统稳定性""优化代码结构""统一调用方式",听起来冠冕堂皇,实际上就是它动了你不该动的地方。遇到这种措辞,直接拉高审查等级。

第二,让 AI 说明它"没有做什么"。我发现在交互时,如果只让它汇报"改了什么",它会把注意力全部放在变化上;如果我追加一句"请明确说明,有哪些可能影响现有系统的文件是您特意没有修改的",AI 反而会自己再检查一遍边界,并且常常能自己发现"我刚才差点改了配置"之类的潜在风险。这个简单的提问技巧,能省下不少 review 审核成本。

第三,建立"AI 安全禁区"文件白名单。现在我在团队仓库里维护了一个ai-restricted-files.txt,里面逐行列出了严禁 AI 修改的文件清单,比如全局配置类、统一响应包装类、数据库访问基类、安全过滤器,然后通过工具链在 AI 生成的结果里做自动拦截。只要 AI 的 diff 触发了任何一行白名单,自动阻塞并强制人工处理。这比任何口头约定都可靠。事实证明,白名单机制是我用过所有防"AI 改坏"手段中性价比最高的一个,强烈推荐。

5. 最后几句实操体会

说了这么多,我其实并不反对用 AI 写代码,恰恰相反,我觉得它是这些年里生产力提升最大的工具。我真正反对的是一种心态:因为 AI 完成功能很快,就默认它也能替你守住系统的边界。现实恰恰相反,AI 最擅长的是把局部任务漂亮地完成,最不擅长的是替系统全局承担风险。它是一把极锋利的刀,但刀不会替你考虑手中还有多少条血管。

我自己现在的工作习惯是:每次拿到 AI 的改动,强制自己先问三个问题:这次它动了我系统中"绝对不能动"的东西吗?它是否只改了任务相关的文件?它有没有想用"更聪明"的方式替我重构某种约定?三个问题里任何一个回答"是",我都会停下来人工亲手确认。这条路走下来,从当初的频繁流程崩溃到现在的稳定精进,我的体会是:强大功能与稳定系统之间的天平,靠的不是信任,而是流程约束。

如果你团队里也正在大规模使用 AI 辅助开发,不妨把我这套思路直接抄过去,尤其是那份"约束提示词"和"禁区白名单"。先难受一个星期,后面你会发现,AI 依然快,但系统,再也没被随随便便改坏过。

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

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

立即咨询