# 我让 AI 帮我修了一个遗留项目的 Bug,过程比我想象的复杂
上周五深夜,一个跑了两年的老项目突然报警。不是什么大事——某个定时任务偶尔超时,数据对不上。但这种”偶尔”最烦人,日志里看不出规律,本地复现也是玄学。
项目是 2024 年用 Python 3.10 + Flask 写的,中间经过三个人接手,代码风格已经混成了大杂烩。有原始的 if-else 地狱,有后来者加的 type hints,还有某任外包留下的拼音变量名。典型的”能跑就别动”型项目。
以前碰到这种问题,我的流程是:打开日志 → 猜问题 → 加更多日志 → 等下次触发 → 再猜。循环三五次是常态。这次我决定换条路,看看现在的 AI Coding 工具到底能不能帮上忙。
## 我选的是 Claude Code,不是 Cursor
这不是说 Cursor 不好。但面对这种”需要读一堆文件才能定位问题”的场景,Claude Code 的命令行模式反而有优势——你可以让它先读日志文件,再读代码库,然后把上下文串起来。Cursor 的 Composer 在单文件场景下很强,但跨文件推理,尤其涉及不熟悉的代码时,我觉得 Claude Code 更合适。
一个细节:Claude Code 可以传整个目录让它先索引。我给了它项目根目录,它自己找到了关键的 `tasks/scheduler.py` 和 `utils/db_retry.py`——这两个文件我本来都没打算给它看,但它自己判断说”这俩可能有关系”。
结果还真是。
## 定位过程:30 分钟 vs 我之前的 3 小时
我把报警时的日志贴给了它,大概 40 行。它问了我三个问题:
1. 这个任务的执行间隔是固定的吗?(是,每 5 分钟)
2. 数据库连接池大小是多少?(我不确定,让它自己找)
3. 超时任务有做清理吗?(没有,这提醒了我)
它从 `config.py` 找到了连接池设置——5 个连接,但任务同时跑 8 个 worker。这就是问题根源:worker 抢连接,部分任务排队等到超时。
找到根因只花了 30 分钟。换以前,我可能要先怀疑数据库性能,再怀疑网络,再怀疑代码逻辑,最后才想到连接池。这个排查路径大概要 3 个小时,而且中间会开很多不必要的 issue。
## 修 bug 的过程:它写代码我擦屁股
定位到问题之后,我让它提修复方案。它给了三个:
– **方案 A**:增加连接池到 15
– **方案 B**:给任务加互斥锁,同一时间只跑一个实例
– **方案 C**:重构用异步连接池,长远方案
我选了 B,改动最小。但它生成的代码有个问题——加锁的逻辑没考虑任务异常退出的情况,锁释放不掉。这在一个跑了两年的老项目里是致命伤。
我指出来之后,它立刻加了 try-finally,还贴心地写了测试用例。但我检查发现,它的测试用例里 mock 的方式不对,因为项目用的数据库 mock 库版本太老(2024 年的代码,用的还是 unittest.mock 的旧写法)。
这提醒我:**AI 生成的代码质量取决于它对你的项目了解多少。如果你不给它完整的上下文,它的”经验”来自训练数据,而不是你的项目。** 这在标准化的新项目上问题不大,但在遗留项目上,细节全是坑。
## 一些数据
这次修复的统计:
– 排查时间:30 分钟(AI) vs 预估 3 小时(人工)
– 代码修改:4 个文件,共 87 行
– AI 生成的代码中,需要我手动修改的:2 处(锁释放 + 测试 mock)
– 部署后观察了 3 天,零异常
从产出效率看,AI 确实帮我省了 80% 的排查时间。但从质量把控看,代码走查这一步完全不能省。
## 我的判断
如果你问我:AI 能替代有经验的开发者去修遗留项目的 bug 吗?
不能。至少现在不能。
但 AI 可以让你从一个需要 3 小时的排查变成 30 分钟。这个差距决定了你是选择”这个 bug 先放着吧”还是”今晚修掉”。对于独立开发者来说,后者意味着你敢接更多活,敢碰更复杂的项目。
我现在的流程变成了:出问题先扔给 AI 读日志和代码,它给出定位和修复建议,我 review 之后再做改动。这个流程下,过去两周我修了 7 个之前懒得动的老 bug。
如果你也有遗留项目里挂着没修的 bug,不妨试一下。最坏的情况也就是 AI 给了一堆废话,但你什么也没损失。万一它真找出来了呢?
