如何阅读源码 ############ 前言 ==== * 读了很多资料 * 源码是最后一步 整体阅读 ======== 代码量级:: 几十 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 的机会 * 享受获取额外知识的喜悦 参考 ==== * [微信 程序人生 陈天]如何阅读一份代码: https://mp.weixin.qq.com/s/e15zfnHYKpZv3TFrksEzfg * 如何阅读一份代码: https://zhuanlan.zhihu.com/p/26222486