我拿 Claude Code 做了一次完整的代码审查,它发现了我没看到的东西
上周五下午,我决定做一件有点极端的事:把我维护了快两年的一个内部工具项目,完整地扔给 Claude Code,让它从头做一次代码审查。
不是让它看一个函数,也不是让它解释某段逻辑——是整个项目,约 8000 行 Python,涵盖数据处理、调度、通知三个模块。
我预期它能发现一些低级问题,然后我回复一句”嗯知道了谢谢”,关掉终端继续搬砖。结果不是这样的。
怎么跑起来的
Claude Code 是命令行工具,安装之后直接在项目根目录执行 claude 就能进交互模式。我给了它一个比较直接的指令:
1 | |
然后等了大约三分钟。
它先花了一段时间索引整个代码库,然后开始按文件给出问题清单。输出很长,我边看边做笔记,把它的发现分成了几类。
它发现了什么
第一类:真正的 Bug
这是让我最意外的部分。它在 scheduler.py 里找到了一个竞态条件——在并发调度场景下,如果两个任务同时修改同一个状态文件,后写入的会覆盖前一个的结果,导致任务状态丢失。
这个问题存在了将近一年。不是每次都会触发,只有在任务密集期才偶发,我一直以为是外部依赖的问题,没往这里查。
Claude Code 给出的定位很精确:scheduler.py 第 247-263 行,两个协程在没有锁保护的情况下读写同一个字典。它直接给了修复方案:引入 asyncio.Lock,代码改动不超过10行。
我验证了一下,确实是这个问题。
第二类:代码气味,但不是 Bug
这一类占了大多数,大概有二十几条。比如:
- 三个模块里有类似的日志格式化逻辑,各自实现了一遍,没有抽公共函数
- 某个配置类用了大量
if-elif判断,扩展性差,建议改成策略模式 - 几处异常捕获范围过宽(
except Exception),掩盖了真正的错误类型 - 数据库连接没有统一的池化管理,每个模块各自建连接
这些我大部分知道,但一直没排进优先级。Claude Code 不只是列出来,还给每条问题标了”影响程度”,用高中低区分。看到有三处被标成”高”,我有点坐不住了。
第三类:它猜错的
它也有几条建议是完全离谱的。
有一处它建议把某个函数的返回值从 None 改成空列表,理由是”调用方可能会直接迭代结果”。但那个函数是有意设计成返回 None 表示”没有数据”,调用方会做判空处理,空列表和 None 语义不同。
还有一处,它看到一个 “TODO: 临时方案,后续改掉” 的注释,建议我把那段代码重构掉。但那个临时方案是因为下游系统还没升级,是外部依赖限制,不是代码问题。
这说明 Claude Code 没法理解业务约束,只能看代码本身的模式。这是它的边界,但如果你不清楚这点,很容易被它带偏。
有一个发现让我印象比较深
在审查通知模块时,它发现了一个潜在的信息泄露问题:错误日志里会打印完整的 API 响应,包括第三方服务的 token 字段。
这是个安全问题,不是性能问题也不是 Bug——程序跑起来完全正常,只是日志里的数据太敏感了。
我自己做 Code Review 的时候,经常盯着逻辑看,容易忽略”数据流”层面的东西。这条让我意识到,Claude Code 在扫描信息安全相关模式上确实比人工敏锐——因为它是在做模式匹配,不是在理解逻辑,反而没有”先入为主”的盲区。
工作流的变化
这次实验之后,我调整了一下个人的 Code Review 流程。
以前的做法是:写完代码,跑测试,提 PR,等同事 Review。这个流程里,Review 是在提 PR 之后的。
现在多了一步:提 PR 之前,先跑一遍 Claude Code 自审,把它标记的”高影响”问题过一遍,确认是真问题的修掉,确认是误判的记下来。
这样 PR 到了同事手里,低级问题已经被过滤掉了,Review 时间明显缩短,同事也更容易把精力放在架构层面的讨论上。
但有一点我需要强调:Claude Code 的审查不能替代人工 Review,它找不到那种”这个设计思路和我们整体方向不一致”的问题,也不知道某段代码背后的历史决策。它擅长的是把明显问题都冒出来,帮你做第一轮筛选。
关于使用成本
用下来,Claude Code 做一次全量审查大概消耗不少 token,8000 行的项目跑完大约花了我 $0.8 左右(用的 Sonnet 3.7)。如果每次提 PR 都跑,月均下来可能要 $20-30。
对个人项目来说这不算什么,对团队来说可能需要算一下 ROI。我的判断是:如果它能帮你在一次 Review 里省掉一个 Bug 的修复成本,这个投入值得。
另外,对大型代码库来说,上下文窗口是个约束——Claude Code 不可能一次性把所有代码都装进去,它会做文件采样。审查质量和代码结构的清晰度有关系,模块化好的项目效果更好。
最后说一句
我原本觉得自己对这个项目熟得不能再熟,哪里有坑、哪里欠债,心里都有数。
但那个竞态条件我真的没看到。不是因为代码写得复杂,是因为并发场景下的状态竞争,用静态读代码的方式很难发现,需要专门去想”两个调用同时发生会怎样”。
Claude Code 的审查没有”专门去想”这回事——它就是在扫描代码里的并发操作模式,看到了这个组合,然后报出来了。
有时候不带前提假设,反而是优势。
相关文章: