本篇要回答的问题:阅读别人的代码为什么本质上是 “架构的反向过程”?带着不同目的去读代码,应该读到什么程度、按什么步骤读,最终产出又是什么?
上一讲谈了 “设计文档怎么写”——那是从思想到代码的正向过程。本讲反过来:当面对别人写的代码、文档又缺失时,如何从代码反推出更高维的架构思想。这是新人融入团队、评估第三方模块时绕不开的基础能力。
为何要读别人的代码?先明确目标
完整读懂一个系统极其耗精力,所以目标决定了你愿意付出的成本。常见目标分四类,对应的投入差别很大:
| 阅读目标 | 投入深度 |
|---|---|
| 评估是否引入某第三方模块 | 浅:理清概要设计与接口即可告一段落 |
| 给某模块局部修一个 Bug | 中:聚焦该 Bug 相关的业务流程 |
| 以某开源模块为榜样去学习 | 中 |
| 接手并长期维护某模块 | 深:需梳理关键业务流程并写成文档 |
读代码 = 反编译,但反推的是思想
读懂源码是架构的反向过程,类似反编译,但不是指令级反编译,而是根据指令反推更高维的思想:
| 反编译类型 | 信息是否有损 | 难度 |
|---|---|---|
| 软件 → 汇编 | 无损,等价变换 | 容易 |
| 软件 → 高级语言代码 | 有损(实体名字多已丢失,符号文件仅供 debug) | 难,需带模型推理、识别 “套路” |
假想一个 “精确还原的智能反编译器” 怎么工作:
| 步骤 | 做什么 | 难度 |
|---|---|---|
| 第一步 | 识别编程语言与编译器(很多编译器有 “署名”) | 容易,粗陋分类器即可 |
| 第二步 | 结合二进制 + 可选符号文件 + 对编译器套路的理解去反编译 | 需持续学习足够多样本,总结套路 |
关键判断:有产出的学习过程才是最好的学习方式。读源码的产出应该是——构建这个程序的思路,也就是架构设计。
理解架构的核心脉络(看概要设计)
概要设计关注各软件实体的业务范畴及它们之间的关系。看源码的标准步骤:
| 步骤 | 做法 | 工具 / 要点 |
|---|---|---|
| 0. 先看文档 | 有文档一定先看,别傻乎乎纯靠代码反推 | 注意文档易与代码脱节,需相互印证,冲突时及时改文档 |
| 1. 整理公开实体规格 | 把公开模块、类、函数、常量、全局变量的规格整理出来 | Go 用 go doc;跨语言用 doxygen |
| 2. 看使用方 | 先看 example、unit test 等 “客户” 代码 | 辅助理解各实体的语义 |
| 3. 初步推测 | 结合规格、文档、example、实体名字隐含语义,推测业务范畴与关系 | —— |
| 4. 证实 / 证伪 | 选重点类或函数读源码理解其业务流程,印证猜测 | 证伪则重新梳理关系 |
| 5. 找前人 | 找做过这块的人争取约 1 小时交流,提前备好疑惑清单 | 大幅缩短理解过程 |
| 6. 写下结论 | 形成文档 | 下一个接手者不必重新 “反编译” |
理解业务的实现机制(看详细设计)
只有在必要时才研究实现机制——研究实现非常费时(UserStory 数量多)。前面读核心代码只为印证业务划分,而非为实现本身。
| 目标 | 关注范围 |
|---|---|
| 评估第三方模块要不要采纳 | 概要设计 + 接口理清即可止步 |
| 顺带解决一个 Bug | 只看 Bug 相关业务流程 |
| 接手新业务系统 | 梳理关键业务流程,无需立刻搞清全部细节 |
搞清业务流程仍靠 程序 = 数据结构 + 算法:
| 步骤 | 做法 | 坑 |
|---|---|---|
| 先理数据结构 | 类成员变量、数据库表结构通常可快速提取 | MongoDB 弱 schema 需读代码理解,且历史多轮 schema 变更在最新代码里看不出,易处理到非预期数据 |
| 再理业务流程 | 给各 UserStory 画 UML 时序图,挑当前最相关的做 | 随时可补充 |
| 写下结论 | 变成架构文档的一部分 | 越多人补充,项目才越能脱离混沌 |
结语与"顺手改代码"的原则
关键判断:代码即文档,代码是理解一致性更强的文档。阅读代码是不可或缺、无法被 “团队默契” 替代的基础能力。
读代码时顺手消除臭味(改几行风格不好的代码)应被鼓励,但要守原则:
| 原则 | 具体要求 |
|---|---|
| 不做大改动 | 单个函数内改动不超过 10 行 |
| 语义完全一致 | 包括所有 corner case:错误码、条件语句边界等 |
| 补全单元测试 | 不管多自信,有改动就补测试,覆盖修改的条件边界 |
总结
读代码的本质是 “反编译”——从指令反推思想。带着明确目标,先看文档、再整理实体规格、借 example/test 理解语义、用核心代码印证猜测、找前人交流,最后写成文档沉淀。深入实现时仍以 “数据结构 + 算法” 为抓手,且只在必要时投入。
先把"是什么"回答清楚
| 概念 | 一句话说明 |
|---|---|
| 读代码 = 反编译 | 不是还原指令,而是反推更高维的架构思想 |
| 概要设计脉络 | 各软件实体的业务范畴 + 它们之间的关系 |
| example / unit test | 研究对象的 “客户”,辅助理解实体语义的最佳入口 |
| 顺手消臭味 | 读代码时改几行坏味道代码,受 10 行 / 语义一致 / 补测试 三原则约束 |
一句话速记
读别人的代码就是一次反编译:先看文档和接口规格搭骨架,再借 example/test 和核心代码反推业务关系,最后把结论写成文档——让下一个人不必重读。
几条值得记住的判断
- 目标决定投入:评估第三方看概要即可,长期维护才深挖实现。
- 数据结构是突破口:理清数据结构,业务流程就解决了大半(当心 MongoDB 弱 schema)。
- 读代码必须有产出:产出就是补全的架构文档,外加顺手消除的几处臭味。
思考题
回到你正在维护的项目:如果今天来一个新人,他能仅靠现有文档读懂概要设计吗?你上一次读懂一段陌生代码后,把 “反编译” 出来的结论写回文档了吗,还是又让它烂在了你的脑子里?

