读别人写的代码是系统程序员最重要也最痛苦的技能。一个
15000 行的 C 代码库,没有文档,注释比代码少,函数名叫
do_stuff 和
handle_event。你被要求在一周内理解它并修一个
bug。
以前的方法:从 main() 开始,跟调用链,画调用图,反复读直到在脑子里建起数据流模型。三天起步。
现在有了一个新工具。不是让 AI 帮你理解代码——它理解得不够深。而是让 AI 帮你做第一遍扫描,标出你应该重点读的 20% 代码。
工作流
第一步:让 AI 生成代码地图
把整个代码库(或关键目录)喂给 AI,要求它输出:
- 模块划分:哪些文件属于同一个逻辑模块
- 调用关系:核心函数之间的调用图
- 数据流:关键数据结构在哪里创建、在哪里修改、在哪里销毁
- 入口点:main 函数或事件循环的位置
AI 在这一步的表现相当好(正确率约 80-85%),因为这是模式匹配——识别 #include 关系、函数调用链、全局变量的使用。
第二步:验证 + 修正
AI 的代码地图不是 100% 准确的。常见错误:
- 把 header-only 的工具函数误认为核心模块
- 遗漏通过函数指针的间接调用
- 混淆 wrapper 函数和实际逻辑函数
用 cscope 或 ctags 快速验证 AI
标出的核心函数是否真的是核心。通常需要 30-60 分钟修正。
第三步:深度阅读 AI 标出的关键路径
AI 标出了 20% 的核心代码。你只需要深度读这 20%。剩下 80% 是:
- 错误处理和日志(重要但不影响理解核心逻辑)
- 配置解析
- 平台兼容性适配(#ifdef 地狱)
- 辅助工具函数
在深度阅读过程中,遇到不理解的函数,直接问 AI:“这个函数的返回值在什么情况下为负数?”AI 在回答具体函数语义的问题时正确率很高(90%+),因为这只需要读懂一个函数。
第四步:用 AI 生成 invariant 假设
读完核心路径后,让 AI 基于代码生成”不变量假设”:
- “这个锁保护的数据结构在持锁期间不会被 resize”
- “这个 fd 在 event_loop 退出之前不会被 close”
- “这个 buffer 的大小在整个生命周期内不变”
然后你逐条验证这些假设是否成立。如果不成立,你就找到了 bug 的候选位置。
实际案例:etcd raft 库
用这个工作流分析 etcd 的 raft 库(前面的文章分析过它):
| 步骤 | 时间 | 产出 |
|---|---|---|
| AI 生成代码地图 | 15 min | 模块图 + 核心函数列表 |
| 验证 + 修正 | 45 min | 修正 3 处错误(间接调用、wrapper) |
| 深度阅读 Step() | 2 h | 理解状态机核心 |
| AI 生成不变量 | 20 min | 12 条假设 |
| 验证不变量 | 1 h | 发现 2 条不成立(edge case) |
| 总计 | ~4.5 h | 核心逻辑理解 + 2 个潜在 bug 位置 |
不用 AI 的传统方法:同样的代码库,我估计需要 2-3 天(16-24 小时有效工作时间)。
节省:大约 3-4 倍时间。
局限性
- AI 不能替代深度阅读。它标出的 20% 你仍然需要逐行读。理解数据流、并发逻辑、错误路径——这些 AI 做不到。
- 间接调用是盲区。函数指针、虚函数表、callback 注册——AI 跟不过去。你需要用 debugger 或 tracing 来补全调用图。
- 大文件效果差。超过 5000 行的单文件,AI 的上下文窗口不够。需要分块喂入,但分块会丢失跨块的依赖关系。
- 不理解运行时行为。代码的静态结构 AI 看得懂,但”这个分支在生产中走的频率”它不知道。profiling 数据是 AI 的盲区。
结论
AI 不能替你理解代码。但它可以帮你在 15 分钟内看到一个代码库的全貌,然后你用剩下的时间去理解它告诉你的那 20%。
从”3 天理解代码”变成”4 小时理解代码”——这不是 AI 替你读了代码,而是 AI 帮你跳过了 80% 的无关代码。
延伸阅读:
- Raft 实现拆解:etcd 的共识算法到底长什么样 – 用这个工作流分析的实际案例
- 让 LLM 帮你写系统代码:哪些能信,哪些会死 – AI 的代码理解能力 vs 代码生成能力
- Go 调度器深度拆解 – 另一个源码考古的案例