主页

索引

模块索引

搜索页面

如何阅读源码

前言

  • 读了很多资料

  • 源码是最后一步

整体阅读

代码量级:

几十 k 体量的代码:
  顶多半年,可以精读
  既不算太过吃力
  也不至于读完意犹未尽

linux kernel级别代码:
  总代码量15406.9k
  分而治之,每次读一部分
  scheduler(20k)
  memory management(80k)

阅读类别:

* 基础阅读
* 检视阅读
* 分析阅读
* 对比阅读

检视阅读方法:

1. 读 readme
 类似书本的「序」
 帮你更进一步了解这份代码的意图

2. 目录结构
 像书本的目录页
 目录下有 readme,快速阅读
 约定俗成的目录结构(Convention by Contract)
 快速知道哪些是可以略过的部分

场景一: 为了破案而阅读

适用情形:

* 遇到奇葩问题
* 查各种资料无果

方法论:

* 顺着一点蛛丝马迹,开始剖析代码
* 抛开一切纷扰和杂音,集中精力,带着线索,循着问题
* 读且只读和解决问题直接相关的代码
* 「猎手模式」
* 专注,集中力量攻击且仅攻击一点

方法之「猜」:

* 「猜」起到了很大的作用
* 连蒙带猜也是解题的一种思路
* 猜文件名,函数名,变量名,某分支,某段代码的意图
* 结合运行的结果,打印调试信息来印证猜测
* 形成有效 feedback loop(read - guess - verify)

操作步骤:

1. 带着线索,从一堆代码中找出和问题相关的代码
2. 专注阅读挑出来的内容,忽略不相干的噪音
3. 编译运行修改过的代码,复现问题,分析调试信息
4. 没答对,请回第 1 步

复盘:

1. 整理过程:
  把整个过程用最简洁的方式记录流水账
  关键代码,关键路径,到达终点的整个猜测过程
  哪些日志验证了猜测是对的,哪些日志验证了猜测走不通

2. 总结:
  这个问题的 root cause 是什么?触发它的代码的流程是什么?
  在读代码的过程中,哪些地方我猜对了,哪些没猜对?
  有功夫的话,代码的哪个部分是值得细细品读把玩的?
  下次再出现类似的问题,我该怎么更快地从源码中定位出问题?

3. 复盘的意义:
  帮你把这样的信息沉淀下来,让你有机会回顾
  进而组织和固化成上篇文章中所说的知识
  这样累积多了,才能形成一个光环,成为砖家

场景二: 为了明理而阅读

阅读对象:

* 算法
* 基础知识
* 理论

正反馈:

* 马太效应
* 读的书多,知道的知识点就多,疑问也多
* 疑问促使你读相关的代码去印证和解惑
* 代码读多了,又感觉理论知识欠缺
* 周而复始

完成后还要做的事:

* 这代码有可以优化的地方么?
* 有潜在的安全漏洞么?
* 是否有未处理的状态或者异常?

总结:

1. 使用「检视阅读」把整个代码过一遍,找到值得阅读的核心代码

2. 粗读这部分代码,将其内容进一步 breakdown
  手边准备好笔和纸,随时记录
  记录最好的方式是图表

3. 精读这部分代码
  结合你已有的知识,理解这个代码所需要的资料
  猜测和还原代码中事件,消息,或者某个流程发生的场景
  把猜测记录下来
  遇到外围的代码调用,可先放一下
  整个过程完整而详细地捋一遍
  这过程要多问问题,减少「我以为我懂了但实际没懂」

4. 用检视阅读法粗读剩下的代码
  如果找到其他值得精读的代码
  跳至 2

5. 对比阅读
 主题阅读
 把类似功能的 repo 都扫一遍
 尝试着用自己的语言消化不同作者的实现
 关注其实现的差异,并试图评判这种差异

6. 用软件将手稿电子化,便于将来回顾
  是个非常耗时的过程
  好为人师,要把你的心得分享出去

场景三: 为了能级跃迁而阅读

目标:

* 打破平台期,成就越级跃迁
* 读代码积蓄能量为跃迁准备
* 读那些基础地不能再基础
* 自己一辈子都不会去写的代码
* 比如 linux kernel,比如 OTP

方法:

* 要有足够的耐心和时间
* 检视阅读 + 主题阅读 + 思维导图

困难:

* 这种阅读有时会让人非常沮丧
* 遇见非常非常之多的 knowledge gap
* 查资料弥补这些你缺失的知识点
* 拉慢了整个阅读理解的步伐

收获:

* 这些 knowledge gap 是上天馈赠的礼物
* 弥补 you don't know what you don't know 的机会
* 享受获取额外知识的喜悦

参考

主页

索引

模块索引

搜索页面