大部分时候,我们接手的都不是“从零开始写”的项目,而是别人已经折腾了好几年的代码库:README 半旧不新,目录层层嵌套,类名函数名一个比一个抽象。

这个时候,如果只是本能地打开 src/ 乱点一通,很容易一下午过去,只留下一个模糊印象——“好复杂”“以后再看”。

下面这篇小册子,想做的就是给这种场景准备一套“读陌生代码库的通用流程”:从先想清楚自己要什么,到从测试和运行结果入手, 再到用工具、调试和提问一点点把系统还原出来。希望它能让你下次面对陌生项目时,不再只是硬扛源码,而是带着方法、有步骤地拆解它。

先想好:我到底想知道什么?

接手一个陌生项目,别一上来就打开 src/ 然后迷失在一堆文件里。先给自己 3 个问题:

  1. 这个项目干嘛用的?(一句话版本)
  2. 我这次的任务是什么?是修 bug、加功能还是评估能不能复用?
  3. 我期望在 今天 / 这几个小时 搞清楚到什么程度?

先定范围,避免变成“研究源码的一生”。

从测试出发

Start from test / Start with an example

如果项目里有测试,那是最适合下手的入口:

  1. 找测试:

    • 常见目录:tests/test/spec/
    • pytest, unittest, jest, vitest, rspec 等关键词
  2. 看“场景”,而不是看每一行断言:

    • 这个测试在验证什么业务?
    • 输入是什么?输出/期望行为是什么?
  3. 记录关键信息:

    • 哪几个模块、类、函数总是一起出现?
    • 出现频率最高的几个名字:基本就是这项目的主角。

如果没有测试怎么办? 那就自己找/造一个最小可运行示例:

  • CLI:看 README 里有没有 example 命令
  • Web:看有没有 demo 页面、Postman collection、curl 示例

了解宏观结构

Get overview of project / Find the High-Level Logic

别像读小说那样从 main.py 第一行看到最后一行。先扫结构:

  1. 看目录:

    • 有哪些顶层目录?api/, core/, services/, models/, ui/
    • 配置在哪?config/, settings.py, .env, application.yml
    • 入口在哪?main.*, app.*, index.*, server.*
  2. 找主流程:

    • 对 CLI:从入口脚本/命令行解析开始看
    • 对 Web:从路由(routes, controller, handler)开始看
    • 对服务:从启动逻辑(main, bootstrap, init)看它都注册了什么
  3. 画一个 非常粗糙 的流程图或模块图:

    • A 接用户请求 → B 做业务逻辑 → C 操作数据库 → D 返回结果
    • 不求细,只要能指给别人看:“大概就这么一套链路”。

先跑起来,再谈理解

Build and Run the Program / Run the project and trace the output / Let the machine help

能跑起来 是理解项目的硬前提。

  1. 尽早尝试 build + run

    • 跟着 README 来一遍,如果失败了,先记下错误,而不是硬扛。
    • 实在不行,就从 Docker / 打包脚本入手看:别人是怎么跑的。
  2. 跑的时候做两件事:

    • 换不同输入,看项目的行为怎么变。
    • 在关键地方加日志 / 断点:

      • 后端:在关键 handler、service、核心算法里打断点
      • 前端:在重要交互/状态管理处打断点
  3. 观察输出:

    • 控制台日志:有哪些关键词反复出现?
    • 错误栈:哪些模块总是在最顶层?

原则: 不要只是“念源码”,要让程序跑起来,跟着程序的行为去看代码。

像在调 bug 一样读代码

If it ain’t broke, fix it. Pretend you are debugging the code.

假装在修一个 bug,是很有效的阅读姿势:

  1. 选一个场景(一个测试用例 / 一个用户操作)
  2. 从入口开始,单步地追踪调用链

    • 断点 → Step Into → 看函数调用
    • 记录:从这个函数出来时,关键变量都是什么样
  3. 一边看一边问自己:

    • “如果这里出错,会怎么表现?”
    • “他们是怎么处理失败/异常的?”
  4. 把这一整条链路用自己的话写下来:

    • 请求进来一路写到结果返回 / 数据落库 / 页面展示

这样看下来,你对项目的理解,会自然聚焦在 真实执行路径上,而不是迷失在一堆看起来重要的辅助代码里。

善用工具,而不是硬扛源码

Leverage the Power of Code Comprehension Tools / Examine Library Calls / Search for Key Words

搜索关键词

从你的任务出发,先列几个关键词:

  • 领域概念:订单、任务、job、pipeline、session…
  • 技术点:缓存、重试、队列、事务、锁、分页…

然后用 IDE 全局搜索:

  • 看这些词出现在哪些文件 -> 这些文件往往是业务核心。
  • 看同一概念是否有多个叫法:job / task / worker,需要记一份“术语对照表”。

看库调用而不是死盯业务细节

Examine Library Calls

当看到一个长函数时,可以先识别它调用了哪些外部库

  • 是通过 HTTP 请求出去?(看 axios, requests, fetch…)
  • 是操作数据库?(query, Repository, Model…)
  • 是发消息?(publish, enqueue, send…)

先搞清楚这些库调用在业务里的角色,代码逻辑就有“骨架”了。

利用 IDE / 工具

  • 跳转定义 / 查找引用: 用 Go to definition / Find usages 追踪一个函数/类是怎么被用的。
  • 结构视图 / 调用层级: 看“谁调用了谁”,“这个类有哪些子类/实现”。
  • 静态分析 / LSP: 比如快速看到类型、参数、返回值,避免靠眼猜。
  • 有条件的话可以用更高级的 code comprehension 工具(call graph、图形化依赖等),但前提是别沉迷工具本身。

边看边写

Writing documentation for source code.

一边读一边写点东西,多少留点“资产”:

  1. 写在旁边的 notes.md / README-dev.md 里:

    • 项目一句话介绍或者架构一句话介绍
    • 核心模块 / 流程的简图
    • 容易踩坑的配置、依赖和启动顺序
  2. 给关键函数/模块补上简短注释:

    • 不要写本函数用于处理 xxx 逻辑这种废话
    • 这个函数在 XXX 场景下被谁调用 / 有什么前置条件 / 返回值有什么坑
  3. 以后再回来时,你看到的就不是“陌生代码”,而是“自己之前留下的路标”。

主动提问

Ask questions.

读不懂的时候,不要把它当成“我太菜”,更可能是:

  • 原本就缺文档;
  • 命名不清晰;
  • 设计经过多轮演化,没人收拾。

这时候要学会问:

  1. 问“懂的人”:

提前整理问题,不要“你帮我讲讲这个项目”。 用具体例子提问:

  • “当用户发起 XX 操作时,这一段调用链是不是这样?”
  • “这个字段是在哪些地方会被写入?”
  1. 问自己:
  • 如果是你来设计,会怎么拆模块?
  • 当前实现和你心里的版本差在哪?为什么?

好的问题,本身就是对代码的结构化理解。

一套可复用的流程

再回顾一下前面流程讲到的流程:

  1. 先弄清任务和目标:这次我需要了解到什么深度?
  2. 找测试 / 示例场景,跑一两个最典型的用例。
  3. 看目录和入口,画一个粗糙的高层架构/流程图。
  4. 跑项目,在真实请求/操作上打断点、看日志。
  5. 选择一条完整调用链,当自己在“调 bug”,从头跟到尾。
  6. 用搜索 + IDE 工具锁定核心模块、关键库调用。
  7. 一边读一边做笔记,补上一点点文档和注释。
  8. 有不懂的地方,先整理,再问人;问完补回文档。

只要大致按这 8 步走,大部分陌生代码库都会从“天书”变成“复杂但可控的系统”。

参考资料