1. 接手老项目的第一天我被“屎山”包围了事情得从半年前说起。我接手了一个运行了将近五年的电商后台系统技术栈是Spring Boot 2.x加前端Vue 2还是老版的Element UI那种。项目本身业务不复杂但代码量积累了三四万行。第一周我看代码看到什么程度每天下班脑子都是糊的因为整个项目根本没有“结构”可言——一个Service类塞了两千行里面混杂着支付逻辑、库存扣减、短信发送、日志上报甚至还有一段写死的主配置文件读取前端的组件到处复制粘贴同一个表单校验逻辑出现在六个文件里各有各的写法数据库查询散落在各处同一个SQL拼了四种方式。这种项目业内管它叫“屎山代码”。不是程序员不爱干净而是项目迭代太急每任开发者都抱着“改完就跑”的心态时间一长整座山就堆成了迷宫。传统重构方式——人肉梳理依赖、手动拆分职责、逐步替换实现——在一座完全没有测试覆盖的屎山面前几乎寸步难行。你改一个公共方法不知道谁会调用跑了线上才炸锅。我之前也试过手动整理用IDE的Find Usage一个个查调用链用postman接口挨个验证甚至想靠写自动化测试把老代码钉住。但进度太慢一个月才拆出去一个类。直到我试了一套AI辅助重构的工作流——借助代码大模型的理解能力配合IDE插件和脚本工具把“梳理依赖、生成迁移方案、批量生成模板代码”这些环节大幅压缩。这篇文章就来聊聊我是怎么把这座屎山一点点拆平、理顺的以及哪些环节AI真的能帮上忙哪些环节它其实是个坑。2. 先别急着让AI生成代码你得知道山到底有多大很多人的第一反应是直接把屎山代码扔给ChatGPT让它帮我重构。我劝你先冷静。让AI直接啃长函数和混乱依赖大模型往往会被上下文长度限制卡死就算硬塞进去出来的结果也是“看起来合理、实际上跑不动”的货。因为AI没有办法验证编译没法知道你项目里那些Bean是怎么注入的也没法知道那个诡异的全局变量是从哪一层传进来的。所以我在实际操盘时第一步根本不是重构而是量化。先把“这堆代码到底烂在哪里”用数据说明白再决定哪些模块优先处理哪些模块可以暂时不管。这一步用传统工具可以做但结合AI能做得更快。我的做法是用SonarQube做静态扫描把项目里复杂度超标、重复代码、坏味道问题全部导出来生成一张问题列表。扫描完我心里大概有数了——这个项目至少有几百个函数超过50行有二十几个类超过1000行重复代码率接近20%。然后我再把这些扫描结果喂给代码大模型让它帮我做一个“重构优先级排序”。这里有个非常实用的提示词模板我整理给你们你现在是一个Java重构专家。以下是本项目SonarQube扫描结果中问题最为严重的若干文件清单包括类名、文件名、行数、主要涉及的坏味道类型列表。请根据以下维度给出优先级排序 1. 文件是否有大量被依赖的公开方法可从调用次数大致判断 2. 是否包含明显可分离的独立职责块 3. 是否有明显的数据模型与业务逻辑混杂物 4. 风险等级高/中/低 输出格式建议用表格包含排序、文件名、优先级、理由说明。跑完这一步之后AI给我的排序基本符合我手算的判断但省了我至少两个下午的阅读时间。它把文件被依赖的程度量化成了文本描述——虽然不能完全替代精确的调用链分析但作为筛选前20%高风险模块的过滤器足够了。然后真正进入了依赖关系梳理。这一步我建议用工具加人工精读的方式不要全靠AI。我在后端用Structure 101的社区版生成模块依赖图在前端用WebStorm的依赖矩阵。两张图对照基本能看出哪几个模块是“上帝模块”级别的核心哪些是老死不相往来的孤立岛屿。把这张依赖图发给AI是后面所有重构的策略基础。AI会基于这个依赖结构输出初步的模块分层建议。为什么不自己拍脑袋因为AI的路径优化能力在这里真的发挥作用了——它在几百个类的关系中能快速找出哪些类更适合被拆出去哪些类应该保留为核心。3. 拆解“上帝类”AI怎么帮我梳理了两千行的逻辑我们项目里有个最糟糕的文件——OrderService光是Java代码就有两千行出头里面包含了下单、支付回调、库存扣减、优惠券校验、订单状态机流转、短信通知、邮件发送、发票开具还有日志上报。一个类承担了八种职责每一次业务规则变更都是在这一个文件里反复横跳牵一发动全身。正常情况下拆这种类需要先列出所有方法然后找出方法之间的字段依赖再按领域职责分组。人工做一遍至少要两到三天。AI帮我压缩到了六个小时但注意不是AI一键生成的是它帮我做了大量“阅读理解”的粗加工。我的具体做法先把OrderService.java全文复制给Claude 3.5 Sonnet附加项目的依赖关系文件简化为pom依赖树和几个核心工具的调用摘要然后用下面这个提示词下面这段代码是一个严重违反单一职责原则的大类。请完成以下任务 1. 按业务子领域把这个类的方法划分成若干个模块分组每个分组起一个合理的类名。 2. 对每个分组列出它依赖的字段、调用到的外部Service、调用了当前类的其他方法。 3. 标出哪些方法之间存在共享的可变状态即同一个实例变量的读写。 4. 最后给出一个建议拆分类的结构——每个新类的职责说明、大概包含哪些方法、以及类之间的依赖关系草图。 注意请尽量保留原始方法的逻辑不要擅自重写业务代码。这个提示词的关键是最后一句——“不要擅自重写业务代码”。很多AI工具默认会“优化”你的代码改逻辑、换写法、重命名变量结果一发不可收拾。我在这里强调只做划分不做重写输出来的结果是可审阅的。AI返回的分组方案老实说基本在点上——它把优惠券校验和订单状态机识别成了两个独立模块把短信和邮件合并成了通知模块把发票开具单独拆了出来。这些分组跟我原本凭经验预想的方案有六成重叠但AI的方案在某些细节上更细致——它注意到了某个私有方法只被同一个业务子流程调用这正是拆分的关键依据。而且它识别出了几个共享状态字段这是一般人扫代码很容易忽略的。OrderStatus、PayInfo这两个字段被七八个方法读写拆类如果没处理好这两个字段的持有方后面就是灾难。AI直接建议了这两个字段应该保留在订单主聚合里而不是跟通知逻辑一起拆走。于是整个拆分计划就成型了。我照着AI给的方案用IDE的Move Method和Extract Delegate逐步落地每拆一个方法就跑一遍编译、跑一遍现有的少量测试再启动服务做一次冒烟验证。整个过程像做外科手术每次只动一个小口子而不是直接把类一刀砍断。这里多说一句传统上大家觉得IDE的自动重构手段Move Method/Extract Class很成熟了但前提是你得知道往哪儿移。AI在这里的价值就是它把“往哪儿移”的决策成本拉低了。以前我需要读半天代码才能判断一个方法跟别的模块的耦合度现在AI直接告诉我候选位置我只需要人工审批即可。4. 前端老页面的“智能改名”运动AI批量操作的正确打开方式后端的上帝类拆完了但并不意味着工作结束了。项目里前端Vue组件的混乱程度不比后端轻尤其是命名——你们能想象一个项目里同时存在orderList.vue、order_list.vue和OrderList.vue三个文件的内容几乎一样吗还有一堆“无用组件”因为没有及时清理留下了一堆名字相似但职责早已被废弃的文件。正常的IDE虽然能用重构的重命名但几百个文件人工一个个勾选眼睛先瞎了。这时候我尝试用AI做“批量代码统计”和“批量命名纠正”。走了两条路一条是用通义灵码和Copilot这类IDE插件扫描符合特定命名规范的文件另一条是用脚本加AI分析的结合——先写一段Node脚本把所有Vue文件列出来分析文件导入引用关系把“没有别处import的孤立文件”筛选出来再用AI对这些孤立文件做分类判断是否可删除。清理命名这里我有一个很深的体会AI给的建议可以采纳但要防止“过度规范化”。比如某次我让AI“给所有变量和方法统一命名风格”它差一点把所有组件里的camelCase命名全部改成另一种风格还顺手把一些模板里用到的短命名展开成了超长描述性变量。结果我费了一个下午把它的“好心”逐条撤销回去。从那以后我所有的AI产物都带一条铁律只允许针对特定清单做修改不允许顺手优化代码里的其他部分。批量操作的第二个用途是给老代码“写注释”。要不要给屎山代码补注释我的答案是要但不要用AI自动补所有注释。原因很简单——AI补的注释往往是对代码逐行的翻译而不是对业务意图的解释补完反而增加阅读负担。真正的注释价值是解释“这段代码为什么这样写”而这类知识只有业务背景里有。所以我只让AI补“导入注释”和“模块级注释”也就是类名上方的说明以及方法级别的行为概要粒度控制在每个方法不超过三行。我不让AI逐行写注释。再强调一遍不逐行。5. 生成技术方案与任务拆解把大重构切成可执行的十几步任何时候重构最忌讳的就是“一次大爆炸”式改动。把整个OrderService一次性拆完等于把风险无限放大——一次改动几百行测试回归无从谈起出了问题根本定位不到。所以我在开始动手之前先要求AI输出一份可执行的方案路线图。我一般这么要求AI现在需要重构以下Java类目标是拆分出5个独立类。请给出一个分步骤的执行顺序每一步的目标、涉及的方法和字段、以及每步完成后应如何验证。要求如下 - 每一步的改动范围尽量小控制在2-3个方法以内。 - 每步完成后都最好能保持编译通过和业务正常。 - 最后给出一个整体回滚策略。AI输出的方案基本是这样的第一步新建OrderStateMachine类把状态流转相关的7个方法迁入同时把订单状态字段封装进该类。第二步新建CouponValidator类把优惠券相关校验逻辑迁入并移除OrderService里对应的本地方法。第三步新建NotificationDispatcher类把短信、邮件、站内信三个方法聚合迁移。第四步InvoiceService用于发票开具依赖改造接入新的注入关系。第五步最后清理OrderService内残留的私有方法确认没有多余引用。每一步都配了验证点——编译、跑起既有测试、手动模拟一单交易。这套方案对靠谱程度比我一开始预想的要细主要是我原先只打算按“支付——通知——优惠券——发货”四大块分四步AI这家伙直接在支付类里又抽出一个状态机对象因为状态流转的逻辑确实独立度高跟支付主流程的耦合不多。要是我人工来拆大概率会把状态机加塞在支付主类里以后还得再拆一次。我后来把这种“AI先出分步方案、我审批后按步骤执行”的模式复制到了前端组件的拆分任务上。流程基本一致——把组件文件结构解析给AI让它给出按功能模块合并和重命名的执行顺序我照着推执行每一步伴随build产出验证。6. AI代码整洁器的工作边界什么能自动什么必须人工把关在分享这套工作流时我最想强调的一点是AI代码整洁器不是“一键清理”按钮。它是一个让你从“人肉读屎山”变成“人肉审批AI建议”的工具本质改变的是你的注意力分配而不是把质量责任外包出去。我在实际的测试项目中有几类操作是完全不敢交给AI自动化的第一涉及外部系统接口的改动。比如支付回调、第三方物流查询、短信服务商API对接——这些外部系统的行为你是无法用单元测试覆盖的AI改错了逻辑往往很难发现。所以凡是涉及外部接口的代码我只让AI做梳理和标注不直接生成替换代码由人工逐字确认。第二并发与事务边界。老项目多少会有些不太规范的并发控制——比如某些地方用了同步块有些地方依赖数据库锁。AI对这些语义的理解经常不准确它可能会把一个本来应该保持原子性的操作拆开引入微妙的数据竞争。我也踩过坑——AI建议把订单支付和库存扣减拆成两个独立Service调用看似职责清晰实际破坏了事务边界差点造成库存超卖。还好在评审时发现了。第三业务强规则与隐含契约。比如项目里有个老逻辑如果用户的手机号以特定数字开头就视为老用户不走优惠券校验。这个规则没有任何注释只存在于某个私有方法的字符串比较里。AI不会理解这是业务规则它很可能把这段代码当成“魔法值”优化掉然后我就等着业务事故吧。所以凡是AI生成的代码我执行前都会问一句这里有没有什么我看不到的隐含假设相反AI完全可以放心的部分包括删除无用import和未使用的方法。这类清理不改变行为风险很低实测下来非常稳。将重复代码提取成公共方法。前提是你给AI明确了几处代码位置和公共方法的输入输出。格式化与命名统一前提是限定范围。生成接口文档和调用关系说明。辅助生成单元测试的骨架。我后来做了一个小表格贴在团队文档里作为“AI自动执行/人工审批/禁止AI改动”三类任务的判据算是给大家定了个边界。7. 从“屎山”到“可以继续生长”的代码三个月的复盘整个项目我前前后后做了三个月。说实话如果把AI全部关掉光靠人工我估计要六个月起步。AI帮我压缩了一半以上的时间但真正让项目“重获新生”的并不只是某个文件变得整洁而是整个团队的思维模式变了。我复盘之后总结了三个核心收获第一AI最重要的价值在“问题定位”而非“代码生成”。在项目初期我花了很多时间试图让AI写“更好”的代码但效果很差直到我调整策略让AI聚焦于“帮我看懂现状、帮我排序、帮我识别耦合和隐藏依赖”时它的实用价值才真正爆发。代码大模型的强项是快速处理文本结构和归纳规律这恰好匹配“梳理代码现状”这个刚需。第二重构要像女孩减肥每一步都能见人。我要求团队的每一次提交都保证编译通过、服务可启动每次只提交几次小改。AI生成方案时如果给的是“一次性大爆炸”式的重构直接驳回重做。分步提交让回滚变得非常容易出了问题能精确定位到是哪一步引入的。第三不要迷信AI生成的“整洁”。有一次AI把OrderService里的一个长方法拆成了三个短方法然后给我自动加了一堆private方法看着很干净。结果我逐个读的时候发现它对业务逻辑的抽象其实是有偏差的——它把两个不同优惠类型给合并处理了因为代码结构上它们长得像。这类“看起来合理、其实错了”的改动是AI辅助重构最大的风险。所以每次AI编译通过、测试通过之后我仍然会挑几个关键业务场景手动走一遍这里省不得。现在这个项目已经跑在重构后的代码结构上了——OrderService从两千行降到了六百多行拆出去的五个独立类各自有了清晰的职责前端重复组件清理掉了三分之一SonarQube的重度坏味道数量从一百多个降到了二十几个。而且最明显的变化是团队里新来的同事看代码不再需要我带着讲一遍来龙去脉了自己读就能懂。这就够了。8. 如果你也要给自己的老项目“祛毒”这套流程可以直接抄结合这三个月踩过的所有坑我把最终的流程重新梳理成一个可直接复用的清单。你不一定非要照着每一步走但照着走至少不会出大乱子。第一阶段摸底与量化。第一步先把项目放到SonarQube里扫一遍或者用开源的ESLint/Checkstyle的规则集做全量扫描导出问题清单。然后用AI对问题清单做优先级排序明确第一批要处理的Top 10文件。注意固定上下文长度文件太大的话分段喂给模型。第二阶段依赖梳理与AI辅助分组。用工具生成模块依赖图后端可以用依赖分析插件前端可以用WebStorm的依赖矩阵把图给AI作为上下文。让它输出拆分候选方案一个大型类/组件应分成哪几块、每块的边界在哪、哪些字段应该归谁。第三阶段人工审批并生成分步执行计划。这一步我建议不省。把AI给的拆分方案拿自己读一遍跟实际业务做一次比对调整不合理之处。然后让AI基于调整后的方案输出分步重组计划——每一步改什么、验证什么。第四阶段按步执行小步验证。每执行完一步跑一次编译跑一次已有测试再手动冒烟一个核心流程。这一步很无聊但最保命。记录每一步的改动内容方便回滚。第五阶段清理残留验证全局。等所有拆分执行完毕最后清一遍无用import、无用方法、重复代码。再起一个全局的回归——重点回归和外部系统交互的流程。这一步建议用真实数据测试而不是模拟数据。整个过程对我最大的意义是把一个曾经“谁都不敢碰、谁改谁背锅”的项目变成一个可以正常演进、新人能快速上手的项目。如果你手头也有一座屎山别想着找什么神器一键清理。把AI当作一个超级快的阅读助手把你自己当作最终的质量负责人这套路至少是能走通的。