☰
用AI Code Review给Python服务瘦身:删掉30%代码的实战记录
2026/10/1 3:38:43 网站建设 项目流程

先说结论:我拿一个跑了半年、将近 2300 行的小型 Python 服务开刀,让 AI 按 Code Review 的标准过了一遍,最后删掉了大概 30% 的代码,功能测试全部通过,线上跑了一周没有出任何问题。这件事本身不难,难的是怎么让 AI 真的像人一样去“审”你的代码,而不是顺着你的思路夸你写得不错。这一篇我把整个过程的思路、操作和踩过的坑都写清楚,希望能给你一个可以复用的方法。

1. 为什么我会想到让 AI 来 review 自己的代码

先交代一下背景。我做后端开发七年,手上维护着一个不算核心但一直在迭代的工单调度服务。这个服务是从一个更早的脚本里拆出来的,早期的代码都是“先跑通再说”,后面陆陆续续加了功能、改了配置、补了异常处理,半年下来,文件变得很大,逻辑也开始绕。

真正让我下定决心清理的是一件小事:有次改需求,我要在现有逻辑里加一个状态分支,结果花了整个下午才搞清楚某个中间变量到底在哪些路径上被修改过。那一刻我在想,这代码是不是已经膨胀到“我自己都Hold不住了”的程度?

最开始我考虑过用 Qt 和 Valgrind 那套传统方案手动理逻辑,但两千多行代码,靠人肉看既费时间又容易漏。我突然想到,AI 在代码生成上已经很能打了,那能不能让它干审代码这活儿?

理由其实很直接:

  • AI 没有“沉没成本”思维。人看自己写的代码,潜意识里会假设每一行都有它存在的理由,AI 没有这个包袱,它只看结构和逻辑。
  • AI 擅长发现模式化冗余。比如重复的错误处理、相似的分支判断、被注释掉的代码块,这些恰恰是大规模重构时最容易忽略的地方。
  • AI 能给出具体的修改建议。不是只告诉你“这段要优化”,而是能说出“这个变量只在两个分支里用到,可以内联”这样有操作性的内容。

但我必须提醒一句所有准备动手的人:AI review 的结果不是免检产品。我把它的输出当作“排查线索”而不是“修改命令”,每一条建议我都自己过一遍上下文,再决定改不改。用人话说就是——AI 给我递扳手,但拧螺丝的还是我自己。

2. 动手前的准备工作:让 AI 看得懂你的代码

直接把这 2300 行代码一股脑丢给 AI,让它“审”,大概率只会得到一个泛泛而谈的总结。我试过,效果很一般。原因不难理解——AI 理解代码也依赖上下文,你要是不告诉它这个模块是干嘛的、有哪些外部依赖、哪些部分是历史遗留,它就只能猜,猜出来的结论当然不疼不痒。

我这边做了三件事,强烈建议你也照着做:

第一,给 AI 一个“业务地图”。我先写了一段一百来字的功能概述,说清楚这个服务是干嘛的:监听 Redis 队列,拿到工单后做状态校验,再分发给下游执行器,最后把执行结果上报,超时的进重试队列。这一段描述非常重要,它让 AI 在审查具体代码的时候能带着“业务合理性”的视角,而不是纯粹看语法和结构。

第二,明确告诉 AI 哪些地方“不要动”。这个很多人会忽略。我们代码里有几段完全是历史兼容逻辑,比如对旧版本数据的字段兼容,以及几个外部系统对接时约定的死格式。这些代码看起来笨重,但碰了就会出事。我直接在 prompt 里写清楚:“以下文件和行号是历史兼容代码,不要建议删除或重构”,不然 AI 一定会忍不住去动它们。

第三,分层喂代码,而不是一次全塞。我把代码按模块分成四个文件,分四次让 AI 审:

  • 入口与任务分发逻辑
  • 状态机与异常处理
  • 各类外部 API 对接逻辑
  • 工具方法集合

每批之间我还加了一些额外的上下文。比如审状态机的时候,我会告诉 AI 系统的合法状态流转路径有哪几条,这样一来它就能判断哪几个分支属于“不可能走到但没删干净”的死路径。

提示:如果你只是自己一个人开发,也可以给 AI 看完整仓库。AI 的上下文窗口现在已经很大了,整仓库看可能有些吃力,但核心文件逐个看完全没问题。关键还是把“背景说明”和“边界要求”说清楚,这决定了 AI 是给你常规建议,还是给你真正有用的建议。

3. AI review 的具体过程:开出的药方长什么样

四轮 review 跑下来,AI 给的建议大致分了这么几类,每一类我都实际处理了一部分。

死代码和不可达分支。这算是最大的收获。状态机里有两个分支,看起来都有人在对它们做修改,但从入口数据来看,那几个值的可能性已经不存在了。AI 用一种很直白的方式点出来的:它说“状态只能是这三个值,但到了第七层判断的时候你还在处理可能是其他值的情况,这层判断永远不会执行”。我也回头翻 git log 确认了这个判断是早期版本遗留的,它的触发场景早已经被入口过滤掉了。这一块直接删掉了四十多行。

重复的错误处理逻辑。服务里有几个调用下游接口的地方,每个接口在调用失败时都有一套几乎一样的重试逻辑:捕获异常、判断错误类型、按类型走不同的退避策略、记录日志,然后决定进重试队列还是死信队列。AI 建议统一抽象成装饰器或者公共方法。这个建议不新奇,我自己也知道应该抽,但平时改需求时总想着“先跑通再优化”,于是一拖再拖。这次既然要做清理,干脆一口气把这些共用的错误处理逻辑收拢起来,变成两个公共函数。代码总量少了,后续维护的时候也少了很多“复制粘贴改一处忘一处”的隐患。

过度设计的通用性。这部分 AI 说得挺狠。我们代码里有一段为了“未来可能要支持多种数据源”而抽象出来的数据源接口,接口下只有一个实现类,而且这个实现类里面还存在大量因为“预留能力”而写出来的分支。AI 的建议是砍掉不必要的抽象层,把实际使用的实现类提上来直接调用。说实话,这个建议一开始我是抗拒的——毕竟抽象这东西,当时设计也是花过心思的。但我看了两眼实际调用方,全工程里只有一个入口在用,确实没有任何复用点。砍!这层抽象拿掉之后,调用链变短了,理解成本瞬间下来了。

安全性和边界防御。当然,AI 也不是只管删,它也会指出一些该加东西的地方。比如在解析外部回调参数的时候,AI 发现我们没有对时间字符串做格式校验,直接就int()强制转换,万一外部传了个非数字,整个进程会炸。这个虽然不算“删代码”,但对整体健壮性帮助很大,属于用同样的成本获得了更高的收益。

四轮跑完,汇总下来 AI 一共提了 38 条建议,我逐条核对后采纳了 31 条,剩下 7 条属于风格偏好问题,或者和现有架构耦合太深,强行改成本不划算,就没动。我手动加了几条 AI 没审查到的修改(比如日志格式统一),总体来说 AI“主线找得还是很准的”。

4. AI 开药方之后,我亲手做的手术:如何确保删完不出事

拿到 AI 的建议清单,真正的工程挑战才开始——怎么安全地删。这是我最想分享的一段,因为这个环节才是清代码最容易翻车的时候。

我的操作步骤是这样的:

第一步,把每个修改拆成独立 commit。我给自己立了个规矩:一个 AI 建议对应一个 commit,绝不合批。比如我删掉状态机死分支就是一个 commit,抽象错误处理又是一个 commit,砍掉过度设计的数据源抽象层再单独一个 commit。这样任何一步出了问题,回滚都是精准打击,不会牵扯其他干净修改。

第二步,逐条验证上下文依赖。不管 AI 说得多有道理,我都会自己 vim 打开代码,把这一段前后翻三遍,确认没有隐藏的外部调用关系,然后再动手。比如 AI 建议某些工具方法没人用可以直接删,我会全局搜一遍确认真的没有引用。这一步不能省——AI 的静态分析能力再强,对于动态 import、装饰器隐式调用这种事也不是百分百灵敏。

第三步,跑全量测试 + 手写场景验证。我们项目里的自动化测试覆盖率还可以,但核心链路还是靠手动场景验证兜底。我把改动后的代码部署到测试环境,按线上真实流程构造了 8 类测试数据,从入队到分发到回调全部跑了一遍,确认没有逻辑回归,才敢放心合并。

有个细节想多说一句:像我这种从脚本演进上来、并没有特别严格执行封版规范的项目,测试用例往往不能完全覆盖所有角落。因此,对“删代码”这件事,把改动范围控制在“不影响外部行为”是最重要的原则。

这里也顺带说一个我踩过的坑:AI 一开始建议我把某段被注释掉的旧逻辑直接删除,理由是“保留它只会造成误导”。这本身没问题,但那段注释里藏着一个环境配置的说明,是当初从别人文档里拷来的,不在代码注释里根本看不到。我要真按 AI 建议连注释一起删了,那个配置信息就彻底丢了。所以删除注释代码块之前,务必先读一遍注释里的内容,防止丢操作文档或排查线索。

提示:如果你也用类似方式清代码,建议删任何注释前先花三十秒扫一遍原文内容。AI 看到“注释代码”会倾向于全部清掉,但里面记录的可能是你未来唯一的线索。

5. 删减完成之后的数据变化与效果复盘

全部改完,我特意统计了一下具体减掉了多少,数字拿出来自己都有点愣:核心代码文件从 2320 行降到了 1610 行,减幅在三成左右。

不过代码行数减少这件事,我不建议当作唯一的成功指标。我更在意的是另外几个维度的变化:

  • 圈复杂度。AI review 之前我随手估算一下,核心模块的平均圈复杂度在 7 到 9 之间,几个状态机相关的文件逼近 15。重构之后整体降到 5 到 6,其中原来最难受的那个状态机文件掉到了 7 附近。这个数懂的人都懂——它直接代表着“你改这个文件的时候脑子要同时存几个分支”。
  • 调试时间。改完后的这周我恰好要对工单流程加一个新节点。放在以前我要先在代码里翻半天,确认哪里改了会影响哪里,这次只花了大概三分之一的时间就把改动点定位清楚了。这就是代码瘦身带来的间接效率收益,非常明显。
  • 错误定位速度。以前线上日志报错,我要在 2000 多行里按调用链一层一层往下找。现在去掉干扰分支和死代码之后,调用链变短,定位问题的速度快了不少。这是我没有预料到的收益,但仔细想想也在情理之中——代码路径少了一半,你在代码里“走迷宫”的时间自然就少了。

代码瘦身不等于无脑删减。我保留了两个我自认为有一定冗余但暂时安全的地方:一个是定时任务模块里对付异常场景的兜底重试代码,另一个是对接旧版客户端时做的字段兼容,这部分一旦出问题时风险代价太高,暂时不动是对的。

6. 从一次删码中得到的三条可复用经验

最后总结一下这次让 AI review 自己代码的实际心得,里面有方法论层面的,也有操作工具层面的,希望对你有参考价值。

第一,AI review 的正确姿势是“给它边界,而不是给它自由”。这个我前面提过,但值得反复强调。直接丢代码让 AI 看,它只能做泛泛的 Code Style 检查——比如哪里缺了 docstring、哪个变量命名不规范,这些当然有用,但完全没触及核心问题。给它业务背景、给定边界约束,它才能真正动脑子帮你判断“这段逻辑是否存在”。而且,AI 还特别擅长跨函数追踪某个变量在代码改动过程中的赋值路径,这种风格恰好适合做死变量分析。

第二,AI 能帮你“减代码”,但“减代码”的价值不在于减本身,而在于降低后续所有改动的心智负担。我拿这个项目当例子:两千多行听起来没有多庞大,但代码复杂度最大的敌人从来不是规模,而是无序。删掉 30% 之后,我对这个服务的掌控感又回来了。不只是自己改得动,后续团队任何一个人接手,也会比原来舒服很多。

第三,配合代码搜索工具能进一步提速。我在用 Copilot 或 GPT 对单块代码做深入分析之外,也会把rg这类全文搜索当作辅助手段,把 AI 标记过“疑似没有引用”的变量和函数全局搜索一遍,双向验证。这个组合方式让我在删代码的时候非常安心。既然我们都要把 AI 当同事使唤,就让它跟你的其他开发工具打通,效果是 1+1>2 的。

第四,别让 AI 的建议替代你的最终判断权。采不采纳,每一条都要给出理由:要么上下文确实主导,要么兼容性制约。在 AI 给出的所有建议中,真正“不用过脑子就可以直接改”的其实只占三成,剩余七成都得结合项目背景做判断。把这个环节做扎实,整个删码过程才算是可控的,而不是一场碰运气。

7. 如果后续还要继续瘦身,我会往哪个方向走

这次删完 30% 之后,我再看了看这个项目的整体结构,发现空间还是有的,只是收益会边际递减。比如有几段本来应该合并的数据库查询逻辑,因为历史原因被拆放在了不同的文件里,这个要合并的话动手术的范围比较大,得等下一次正常迭代周期里顺带做。再比如几个回调接口的参数解析部分,逻辑高度相似但细节差异太大,AI 和我都认为现在强行抽象会得不偿失——这类代码属于“可容忍的重复”,先留着比先重构稳。

所以如果你也在计划做类似的事,我的建议是:别指望 AI 一次帮你把代码减到极致,更重要的是建立起一套“代码需要定期清理”的意识。让 AI review 不需要挑什么特殊时机,任何一个迭代空隙都可以跑一轮,每次哪怕只找到 5% 的冗余,坚持几个版本下来,积累的收益也非常可观。

工具已经摆在这里,能不能用好,核心还是你对自己的代码有没有“下得去手”的勇气,以及有没有给 AI 足够的上下文让它替你分担判断——这比输入什么样的 prompt 技巧重要得多。

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

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

立即咨询