Claude Opus 5.5(High)#
通用的方法论可以浓缩成一句话:读代码是搜索,不是读书。 不要从第一个文件读到最后一个,而是带着具体问题,在代码里找证据。
下面这套流程不管你的目的是什么都适用。
总流程:目标 → 地图 → 锚点 → 追踪 → 验证 → 记录#
0. 把目标改写成可验证的问题#
"看懂这个项目"太模糊,没法判断什么时候算完成。要把它改写成一个具体的问题:
| 模糊的目标 | 可验证的问题 |
|---|---|
| 了解 A 和 B 的关系 | A 在什么时候、通过什么方式、给 B 发了什么? |
| 修一个 bug | 输入 X 时,哪一行代码让结果变成了 Y? |
| 加一个功能 | 一个类似的已有功能是怎么实现的?我要改哪几处? |
| 学习架构 | 一个典型请求从进入到返回,经过了哪些层? |
| 安全审计 | 外部输入从哪进来,最后流到了哪些危险操作(exec、SQL、文件)? |
| 升级或迁移 | 项目依赖了旧版本的哪些 API,分别在哪里? |
问题越具体,后面每一步越不容易跑偏。 读着读着迷失了,就回来看看这个问题。
1. 建立地图(每个项目只做一次,15–30 分钟)#
不管目标是什么,先花一点时间回答下面五个问题,答案写在一页纸上就够:
- 它是什么? 读清单文件(
package.json、composer.json、info.xml、pom.xml、go.mod……)和 README。 - 用了什么框架? 框架决定了"代码是怎么被调用的",下面单独讲。
- 入口在哪? 比如
main、路由表、CLI 命令、定时任务、事件监听、index.php。 - 目录怎么分? 通常一级目录看名字就能猜出职责,只需确认 2–3 个。
- 怎么跑、怎么测? 看 Makefile、scripts、CI 配置(
.github/workflows)和tests/。
另外有几个文件值得优先找:docs/、CONTRIBUTING.md、AGENTS.md/CLAUDE.md、ARCHITECTURE.md。作者亲自写的说明是信息密度最高的资料。
2. 找锚点:在代码里找到第一个落脚点#
有了问题之后,要找一个能直接搜到的东西作为起点:
- 用户能看到的字符串:报错信息、界面文字、日志内容。这是最好用的锚点,直接全局搜。
- 外部接口:URL 路径、命令名、配置项名、环境变量、数据库表名、端口号。
- 名字:类名、app id、命名空间、文件名。
- 测试:测试名往往直接描述了功能,测试代码本身就是"怎么调用它"的示例。
- 历史:
git log -S "关键词"能找到引入某段代码的提交,提交说明往往会讲清楚它为什么存在。
上一次的分析里,锚点就是 app id richdocumentscode 和文件名 proxy.php。
3. 从锚点出发追踪#
追踪有三个方向,要有意识地选择:
- 向上追:谁调用了我? 用 IDE 的 Find Usages,或者 grep 函数名。适合回答"这段代码什么时候会执行"。
- 向下追:我调用了谁? 跳转到定义。适合回答"这段代码具体做了什么"。
- 追数据:这个值从哪来,到哪去? 适合函数调用链断掉的时候。
调用链"断掉"的地方往往就是答案所在,常见的有这几种:
- 配置、数据库、缓存(一边写,另一边读)
- HTTP、RPC、消息队列(跨进程)
- 事件、钩子、回调(发布者不知道订阅者)
- 框架的依赖注入、路由注解、反射(代码里看不到显式调用)
遇到断点时,就换成追那个共享的值:key、URL、事件名、表名。
控制深度:每往下跳一层,都先问一句"这一层和我的问题有关吗?"。无关的函数只看名字和签名,猜一下它的作用,标记为"未验证",然后继续往前走。
4. 验证:区分"读到的"和"猜到的"#
纯读代码的结论,有一部分是推断出来的。手段从轻到重:
- 找第二处证据:比如一个调用点、一个测试、一份文档,能互相印证就够。
- 跑起来观察:浏览器 Network 面板、日志、
strace/抓包。 - 加打印或断点:确认某段代码真的执行了、某个值确实是你以为的那样。
- 写一个小测试,或者改一行看会怎样:最直接的因果验证。
不是每条结论都要跑起来验证。但关键路径上的推断至少要有两处证据。
5. 记录#
每次分析结束时留下三样东西:
- 一张链路图或流程图,每条线都标上
文件:行号 - 结论清单,标明哪些已验证、哪些是推断
- 未解决的问题
下次再看这个项目,或者把结论讲给别人听时,这份记录能省下大部分时间。
框架:最容易卡住新手的地方#
陌生项目难读,很多时候不是代码难,而是框架替你调用了代码,而你看不到调用方。所以遇到新框架时,先弄清它的"生命周期",也就是一个请求或事件是怎么进到你的代码里的:
| 要搞清楚的 | 举例 |
|---|---|
| 路由怎么映射到函数 | 注解/属性、routes.php、urls.py |
| 对象从哪来 | 依赖注入容器、构造函数自动注入 |
| 有哪些隐式入口 | 中间件、事件监听、定时任务、生命周期钩子 |
| 约定的文件位置 | appinfo/、migrations/、templates/ |
上一次的分析就用到了 Nextcloud 的两条约定:#[FrontpageRoute(url: '/autosetup')] 对应 apps/richdocuments/autosetup,以及 OC.appswebroots 里列出已安装的应用。不知道这些约定,代码就会看起来"断了"。
做法:读框架官方文档里讲"请求生命周期"或"应用结构"的那一章,通常一小时以内就能读完,后面会省下很多时间。
按目的的侧重点速查#
| 目的 | 锚点从哪找 | 重点关注 |
|---|---|---|
| 找调用关系 | 被调用方的名字、接口 | 耦合方式,以及调用链断开的地方 |
| 修 bug | 报错信息、复现步骤 | 先复现,再缩小范围,最后定位到具体的行 |
| 加功能 | 最相似的已有功能 | 照着它改;它涉及的文件就是你的修改清单 |
| 学架构 | 入口和一个典型请求 | 分层、模块边界、数据怎么流动 |
| 安全审计 | 外部输入点 | 输入一路流到 exec、SQL、文件、网络的路径,以及中途的校验 |
| 性能 | 慢在哪(先测量) | 循环里的 IO、N+1 查询、缓存 |
| 升级或迁移 | 依赖清单、弃用警告 | 旧 API 的所有使用点 |
工具#
- ripgrep / grep:第一工具。要学会用
-g排除vendor、node_modules、l10n,减少噪音。 - IDE:跳转到定义、查找所有引用、调用层级(Call Hierarchy)。你的项目里已经有
.idea,PhpStorm 用好这三个功能就足够了。 - git:
git log -S、git blame、git log -- 某文件,用来查"为什么这么写"。 - 调试器和日志:用于验证。
- AI 助手:适合用来"快速建立地图"和"解释一段看不懂的代码"。但要让它给出
文件:行号证据,并且自己去核对关键结论。
常见误区#
- 从头逐行读:读得很累,记不住,而且大部分内容和你的问题无关。
- 一路钻到底:每个函数都点进去看,三层之后就忘了自己在找什么。
- 只追函数调用:遇到配置、HTTP、事件就断了线。这时候要改追数据。
- 忽略框架约定:觉得"这个函数没人调用",其实是框架在调用。
- 把猜测当结论:没有核对就写进结论,后面的推理全建在沙子上。
- 在生成代码和第三方代码里浪费时间:
vendor/、dist/、node_modules/一般跳过。
一个练习建议#
用同一个项目、换一个目标再练一遍,效果最好。比如:"在 Nextcloud 里点击打开一个 .docx 文件,到编辑器显示出来,中间发生了什么?"
- 锚点:前端的打开文件逻辑(
src/里搜urlsrc),以及后端的DocumentController - 会遇到的断点:iframe、
postMessage、WOPI 回调(WopiController) - 产出:一张从点击到显示的时序图
你按上面的流程自己走一遍,有卡住的地方或者想核对结论,可以随时拿来问我。