
最近和不少做后端的、做前端的朋友聊下来大家都有一个共同的感受代码库正在变得越来越“不敢动”。模块能跑、接口能调、测试全绿但每一次改动都会牵扯出一连串你完全没读过、也没看懂来龙去脉的代码。它们纠缠得如此巧妙像一座用无数胶水粘起来的积木塔——表面看着没问题往深了碰就开始哗哗往下掉渣。这个锅不能全甩给业务复杂过去一年大热的 AI 编程工具“贡献”相当大。Cursor、Claude Code以及它们身后一整代“生成式 IDE”确实把写码效率拉满了但与此同时代码屎山的形成速度也被拉满了。过去一个团队可能花三年五年才能堆出一座像样的屎山现在一个季度就能把代码库变成谁都不想碰的废墟——而且还显得特别精致因为每一段代码单独拎出来都还算体面。我不是来唱衰 AI 编程的我自己就是这些工具的深度用户。但用了这么久我发现一个很不对劲的趋势很多人把 AI 当成了“不需要做设计的外包程序员”而不只是一个加速输入的工具。这篇文章想把这个事情掰开揉碎讲清楚——号称要拯救我们的 Cursor 和 Claude Code到底是怎么把代码库一步一步喂成屎山的以及有哪些可落地的招数能挡住这个趋势。1. 代码屎山的形成机制与 AI 为何成为加速器1.1 什么算“屎山”它跟“代码乱”是两回事很多刚开始写代码的同学会把屎山理解成“缩进不规范”“变量命名太随意”“没写注释”其实这是把脏代码说小了。真正的屎山是结构层面的债务模块之间循环依赖、同一份业务逻辑散落在七八个文件、一个基础类被无数个地方局部 override、没有任何测试能保证重构后行为不变化。它最可怕的特征不是“丑”而是“改不动”——你不知道动了这一段会在哪个角落炸出线上事故。用生活化的说法代码库就像一套老房子。脏乱只是表面问题真正致命的是承重墙被砸了、水电管线乱拉、每一任房东都按自己的审美重新装修过。AI 编程工具的可怕之处恰恰在于它在疯狂加速“换房东”的频率。以前一年换一任房东现在一个 sprint 能换三轮而且每轮装修都看着挺像样的等你想住安稳点的时候墙里全是问题。所以在聊 Cursor 和 Claude Code 之前我们得先对“屎山”有个共识它不是简单的代码风格问题而是系统在结构层面失去了可维护性。这个共识很重要因为后面讨论 AI 工具怎么闯祸都是围绕结构来的而不是盯着某个缩进哭。1.2 AI 生成代码的三个加速效应为什么 AI 工具会加速屎山化我总结了三个层面这也是后面所有风险分析的总纲。第一生成速度快到思考跟不上。以前写一个函数从敲键盘到运行你的大脑其实在完成两件事组织逻辑、评估方案是否合理。AI 补全把“组织逻辑”压缩到了几秒钟代价就是“评估方案”这个环节被大多数人直接跳过了。代码不是想清楚才落盘的是想都没想就已经躺在编辑器里了。速度越快欠的思考债越多。第二局部优化很强全局一致性极差。Cursor 和 Claude Code 都非常擅长根据当前打开的上下文文件生成“看起来合理”的代码但它们很难真正理解整个系统的架构约束。于是你会发现同一个概念今天生成一个 UserService明天生成一个 UserManager后天又冒出个 UserUtils三个类各自实现一套差不多的逻辑彼此之间还完全不知道对方的存在。第三坏味道会形成正反馈循环。大模型生成代码依赖的是你代码库里现有的内容。一旦你代码里有复制粘贴的风气、吞异常的习惯、超长函数的恶趣味AI 会非常忠实地把这种风格“继承”下来甚至放大。垃圾进、垃圾出这是所有数据处理系统里绕不开的铁律大模型也一样。而且因为 AI 的平均产出质量并不低它生成的屎山代码比人类写的还要“专业”迷惑性极强。2. Cursor高效补全背后的隐性风险2.1 爽感背后的心理陷阱把“正确性”外包出去了先说 Cursor。这是目前我用过的最接近“第二大脑”的编辑器补全流畅度确实高得离谱Tab 键一敲一整段像模像样的代码就出来了。写样板代码、测试桩、日常工具类的时候爽感是之前 VSCode 挂一堆插件完全没法比的。但正因为太爽了一个特别危险的心理陷阱就来了你默认它生成的是“正确的”。我在项目里见过不少朋友把 Cursor 当成自动填表器光标一停就 Tab、Tab、Tab一个文件改完了还不知道里面到底写了什么。这里核心问题不是“AI 会不会写错”而是“你没看怎么知道它对不对”。没经过你脑子校验的代码片段在合入代码库的那一刻就是一颗屎山种子。你可能会说代码 review 会拦住的。事实上我观察到的现实是当 AI 生成代码的体量变成常态reviewer 根本盯不住那么多细节最后 review 就退化成了回车确认。而且人有个毛病对“机器生成的东西”天然会降低戒备心仿佛自动补全的代码自带可信度这比人写的 bug 还难防因为人写的烂代码你会有警惕AI 写的烂代码你反而没有。2.2 三个真实风险场景我全都踩过我归纳了 Cursor 最容易导致屎山扩张的三个场景都是实际项目里反复见过的。第一个是“过度捏造”。你让它实现一个它只懂一半的业务需求它特别热心会帮你“补全”一整套流程多出来一个你根本没要求的状态机、缓存策略、重试机制。这些附加内容在你没注意到的瞬间就进了代码库。表面上看这段代码很健壮实际上它引入了一堆没人理解的设计决策之后的每一任维护者都只敢加代码不敢删逻辑。第二个是“重复代码爆发”。Cursor 非常擅长复制你已经写过的写法贴到新地方做点小改动。听起来没问题但执行起来你会发现代码膨胀得惊人同一个校验逻辑能出现在十多个文件里每个文件里的写法还微妙地不同。需求一变就得改十几个地方漏一个就是事故。以前这种复制粘贴需要手动做好歹还有个“看一眼再粘贴”的环节Cursor 把这个环节直接干掉了。第三个是“上下文盲目自信”。Cursor 的上下文窗口是有限的模型只会看到你当前打开的文件和夹带的若干片段。可它生成代码的时候表现得像是已经理解了整个项目的所有设计约束。这类代码放到全局里去往往是在错误的地方调用了错误的东西或者绕过现有抽象自创了一套平行宇宙实现——然后这套平行实现又成了新推广的“样板”。2.3 Tab 补全正在偷走程序员的“负责感”我特别有感触的一点是过去写代码哪怕你是复制粘贴总还是有个“看一眼”的动作。Cursor 之后这个动作被极大地压缩了。我认为它真正在剥夺的是程序员最核心的东西——对自己写下的每一行代码负责的警觉心。也不是说 Cursor 就不能用而是得有一个清醒认知Cursor 给你的补全本质上是个“完美小助手”的幻觉它不是代码评审者更不是架构师。用它的正确姿势是让它帮我们省掉输入成本而不是替我们承担思考成本。省掉输入成本的时候大脑依然在线你知道这个代码是干嘛的替你承担思考成本的时候你只是手指在动脑子和屎山已经同步上线了。工具本身没有意识它不会惩罚你的偷懒但代码库会。3. Claude CodeAgent 式编程的风险形态和 Cursor 完全不同3.1 它是终端里的“远程兼职程序员”不是 IDE再来说 Claude Code。它和 Cursor 是两种完全不同的物种。Cursor 是在 IDE 里跟着你输入的补全助手而 Claude Code 是跑在终端里的 AI Agent你直接给它一个任务它可以自己读取项目文件、执行命令、修改代码、跑测试然后把结果反馈给你。换句话说它不像助手更像一个“远程兼职程序员”——你给它派活它自己上手干。这种模式上限更高但风险也完全不同。Cursor 的风险在于“你没看清就接受了补全”Claude Code 的风险更进一步你根本不知道它在你看不到的地方做了什么。它完全有可能把五个文件串联着改了有可能擅自重构你正在用的函数签名还有可能为了把测试跑绿在配置里塞进你根本不知道的环境变量。你最后拿到的只是一个结果至于过程它只会给你一个轻描淡写的总结。3.2 三个 Agent 翻车现场每一个都让人血压飙升我实际使用和观察到的失败模式基本可以归成三类。第一类是“自作主张把改动范围扩大化”。你让它修一个小 bug它通过检索代码判断根源在另一个模块于是把那个模块的逻辑也顺手改了。最后 diff 一展开十个文件八百行改动。它还会理直气壮地告诉你“这是必要的重构”。问题是没人知道它是怎么推理出这个必要性的这类改动也极难 review——十个文件牵在一起你敢随便回滚吗第二类是“报错循环里的假修复”。Claude Code 在执行测试时失败了它会进入自我修复循环改一行、跑一次、报错、再改一行。问题在于它可能并不是在修复问题的根源而是在用各种看起来无害的小补丁绕过报错。我见过它为了应付 null 指针在调用处疯狂加判空为了通过边界测试直接写死特判。最终测试绿了坑也埋得更深了。这种“假绿”比“真红”还要麻烦因为它骗过了 CI也骗过了团队里所有人的警觉。第三类是“上下文蔓延带来的概率性失控”。Claude Code 的上下文量确实很大但再大也没法穷尽一个中型项目的全部细节。在长任务里它会逐渐遗忘早前你明确否定的方案或者把已经推翻的设计重新捡回来。如果你的指令不够收敛它的行为会越来越像一只精力充沛但方向不明的仓鼠跑个不停代码库却被改得越来越不像样。3.3 上下文窗口再长也替代不了项目的隐性记忆这里我要泼盆冷水。很多人觉得 AI 上下文窗口越来越长以后是不是可以完全放手让 Agent 管整个代码库了我的答案很明确不行。原因不是技术参数不够而是“全局一致性”从来不只是信息量的问题。一个代码库真正的记忆除了每个文件的内容还包括那些根本没写进代码里的决策为什么这里不做缓存、为什么这个接口用这个命名而不是那个、为什么这段逻辑死活不能拆到公共模块。这些隐性知识不在一行行的代码里它们散落在大家的脑子和历史讨论中。AI 工具能在信息层面帮你“记得”但它很难在理解层面替你“判断”。一旦它开始全权负责你丢失的不是文件内容而是决策依据——而屎山最深的根就是从决策依据丢失开始的。Cursorm和 Claude Code 的差别也可以简单看这张表项目CursorClaude Code交互形态IDE 内补全 对话终端命令行 Agent工作半径当前文件 可控上下文可执行命令、修改任意文件核心风险不假思索地接受补全自主改动超出预期范围治理难度相对可控盯 diff 即可需要更强的沙箱和审批机制典型失控现场重复代码爆发跨文件传导式重构4. 沉默的吞噬AI 如何反向重构你的架构4.1 功能边界是被“最小改动”一点点啃掉的说完了两种工具的各自风险我想往深一层挖为什么 AI 参与越多架构越容易被啃坏关键在于 AI 的一个底层习惯——永远选择“最小改动路径”。表面上这很合理改得少风险小。但“最小改动”和“正确改动”经常是矛盾的。比如一个支付抽象层本来很干净AI 拿到一个新需求它会倾向于在现有函数里继续加代码而不是去抽象重构。这不是因为它笨而是因为它被训练成输出“最符合当前上下文延续性”的结果而“重构”恰恰意味着打破上下文延续性。于是几轮迭代之后你那个原本干净的支付抽象层会变成掺杂数据库查询、外部 API 调用、日志上报和促销判断的怪物。每一处改动单看都可以理解但结合起来就是结构灾难。更可怕的是这个过程是渐进发生的每个版本都只比上一版丑一点点团队很难察觉等到发现时就已经病入膏肓了。4.2 屎山会传染从文件级混乱走向模块级混乱代码屎山和传染病很像有很强的传染性。早期可能只是某个新文件比较乱。但如果 AI 一直在那个乱文件附近迭代乱象会以它为中心向外辐射后续生成的代码会越来越倾向于迁就这个乱文件而不是清理它。很快整个模块都变成“历史包袱”状态所有新代码都在给它打补丁。到了这个阶段测试依然可能是绿的功能依然正常但团队里每个人都知道这个模块不能再碰了。于是新需求只能绕过它在别处另起炉灶再造一个平行的模块然后重复同样的过程。一两个季度之后代码库里可能就多出十几个“重影模块”每个都承担着差不多的职责但各有各的写法。到这一步再想治理已经不是重构一两段代码了而是要做一次架构级手术——成本高到大部分团队会选择继续苟着。4.3 五个预警信号你的代码库正在被“吞掉”我这里整理了五个早期信号你可以拿自己项目对照一下git 提交里AI 生成的批量改动越来越多diff 动辄几十个文件。同一个业务概念类名和函数名开始五花八门找不到一个明确的“权威实现”。模块间依赖关系极其难画几乎不存在清晰的单向依赖。改一个简单需求总需要连带改动好几个无关文件。review 时越来越难看懂别人的 PR因为代码风格统一了设计意图却一团模糊。这些信号单独出现任何一条都不一定说明有问题但如果同时出现三条以上你大概率就已经处于“AI 高速帮团队堆屎”的进行时了。早发现早治理拖到后面成本是指数上升的。5. 危机责任链工具、流程还是人5.1 工具只是放大器不是屎山的源头写到这里得说句公道话了屎山的锅不能全让 Cursor 和 Claude Code 来背。工具本身是放大器。你本来就有屎山AI 只是让它长得更快你本来架构清晰AI 大概率也会沿着相对干净的路径走。真正决定代码库走向的还是团队怎么用这些工具。这也不是给 AI 工具洗白它们确实引入了新的失效模式——过度自信、上下文遗忘、最小改动强迫症这些都是传统工具没有的问题。但如果流程控制到位AI 就是一个强大的效率工具流程形同虚设的情况下指望 AI 自动管理好架构那它就会变成一台马力十足的屎山挖掘机。同样的工具怎么用决定了它是帮手还是帮凶。5.2 新手和老鸟用 AI结果天差地别我观察到一个特别有意思的现象同样用 Cursor 和 Claude Code新手和老手交出来的代码库质量完全是两个物种。新手更容易把 AI 当成“答案生成器”遇到需求直接甩给 AI拿到结果就提交老手则更习惯把 AI 当“编码加速器”先自己把设计方案、接口边界、改动范围想明白再让 AI 去处理“写代码”这一步。差别就在这一步认知屎山不是编码速度导致的而是决策速度导致的。新手把决策权外包给了 AIAI 虽然快但它的决策没有经过架构语境的校验老手保留决策权只是把打字和查 API 的时间省了下来。所以说 AI 编程最大的危机其实是把它当成了“不需要做设计的外包程序员”——跟用哪个工具关系不大主要看你的脑子在不在决策链路上。5.3 用“可逆性”当价值判断的新准则那要怎么判断一次 AI 参与改动到底是好是坏呢我自己这几年下来慢慢形成了一个朴素的判据看这个改动是否“可逆”。如果一次重构之后你可以很轻松地撤销、回滚有充分的测试验证行为没变那这次改动就是健康的。如果改动让代码变得更难测试、更难局部理解、更难单独回滚那不管表面看起来多智能你都在往屎山添砖。把“不可逆风险”控制住AI 的很多毛病就不会致命控制不住一次“聪明”的重构可能就是一个月的噩梦。这套判据也从侧面说明测试覆盖不是可有可无的环节它就是你给 AI 折腾设下的安全绳。6. 从屎山里救场我目前实行的 AI 编程管控清单6.1 先画一个圈再在圈里随便飞说了一堆风险和原理最后落回到可操作的东西上。我现在管理 AI 编程工具的做法核心就一句话先画一个圈然后让你在圈里随便飞。具体怎么落地第一明确规定 AI 可以改什么范围小的 bug 修复、样板代码、测试用例可以放心交给 AI核心架构、跨模块重构、数据库变更必须人来主笔AI 只能当草稿工具。第二所有 AI 生成的较多文件改动一律走分支提交不允许直接推到主分支确保每批改动都能在独立环境里验证。第三给 AI 立军规不擅自改函数签名、不擅自加依赖、不擅自重构无关代码。这些规矩写进团队规范最好直接写进工具的规则文件让 AI 从第一行代码开始就带着镣铐跳舞比事后指责高效得多。6.2 代码审查和测试在 AI 时代是保命符代码审查在 AI 时代不是变轻松了而是变得更关键。我强烈建议团队把 review 的门槛调高AI 产生的 diff必须有人能够逐行看懂。看不懂当场就问问不清楚就要求重写。千万别因为“CI 过了”“测试绿了”就放心合入——那等于给屎山开了最高权限。同时测试覆盖是 AI 生成的最后一道栅栏。尤其是 Agent 做大范围改动的时候必须配套清晰的单元测试和集成测试。没有测试的地方AI 发疯你根本不知道。我会要求 AI 重构完某个模块后先把测试补齐再谈提交。测试不只是防回归它同时是给 AI 一个客观的行为反馈环让它能区分“我改对了”和“我改错了”。给你一条我在实践中被毒打多次后总结的规则AI 生成的代码必须满足三个条件才允许合入——有人看得懂、可以回滚、有测试保护。三个条件缺一个宁可返工也不要将就。6.3 几个实战细节规则文件、生成后检查和定期清理最后分享几个直接能上手的实战细节。很多人问 Cursor 怎么设置中文界面、Claude Code 怎么安装配置这些基础问题网上一搜就有我更想讲点“防屎山”相关的配置习惯。第一善用工具的“规则文件”和“记忆机制”。Cursor 支持项目级规则Claude Code 也有自己的系统提示配置把团队的编码规范、禁止事项、默认风格写进去比如“所有新增逻辑必须优先放入已有 service 层”“禁止在 controller 里写业务判断”“命名必须遵循现有英语名称体系”。这能显著减少 AI 生成的“自由发挥”把它的创作欲收敛到合理范围。第二“生成后必做三件事”。AI 生成完代码后不管看起来多合理统一要求先读一遍改动、再跑一遍相关测试、最后手写两行注释说明设计意图。这三件事做完大部分屎山种子在被提交之前就被掐死在编辑器里了。听起来简单但执行到位比任何高级功能都管用。第三定期反向清理。我会每周挑一个 AI 改动最频繁的模块主动做一轮“反向清理”——删冗余代码、合并重复逻辑、修正命名。花不了多少时间但能抵消 AI 高速堆杂物带来的熵增。这个习惯我坚持了大半年效果很明显AI 仍然是团队里的主要写码工但代码库的混乱程度没有跟着指数上涨。说明“圈养式使用”是完全可行的。我个人现在越来越确信一件事Cursor 和 Claude Code 确实是划时代的工具但它们替代不了你的判断力。工具一定会越变越强屎山危机的解法却始终在人这边——上线之前多想一步审查时多问一句提交前少偷一次懒这些最终都会在代码库里兑现。别让 AI 替你写代码变成真的替你做决策那是目前为止我见过最贵的屎山门票。