源码是一个终点静态、复杂度静态、边界清晰的学习对象, 它有静态的学习内容、学习目标、学习结果
源码是编写出来的, 编写者有一个自己的编写者上下文, 而之所以阅读源码, 是因为缺乏编写过程的上下文, 只有一个初始空白的读者上下文; 之间的关系类似于汇编和反汇编, 关系分别是 “从人类想法到代码书写” 和 “从代码书写到人类想法”
编写者上下文和读者上下文是有显著区别的:
源码的阅读过程是“先苦后甜”的, 并大致有这样一个模型:
START -> Symbol main
Symbol deep(1) deep(1) deep(1)
Symbol deep(2) deep(2) deep(2) deep(2)
Symbol deep(3) deep(3) deep(3)
END -> Symbol deep(max)
起始时, 在一无所知的情况下, 阅读一个符号会接触到更多的未知符号, 即“学的越多越无知”, 但是源码的内容是有限的, 因此必然会到一个阶段, 就是新增的未知符号从越来越多变为越来越少
确定核心目标后, 再确定一个核心目标相关的“小”目标: 不要一开始就找 main 文件开始阅读(但可以浏览), 从 main 文件开始阅读的未知符号数量是最多的, 应当从 main 链路中找到一个相对独立的模块, 作为单次的小目标消化局部复杂度, 然后最终通过 “链接” 小目标的学习结果, 消化整体的复杂度
需要注意, 初次挑选的小目标, 可能还是很大, 目标应当继续缩小
编写者的编写习惯和读者的编写习惯是不一致的, 特别是大型项目有 N 多新的老的编写者的情况下, 代码质量其实未必佳, 因此最好阅读的时候, 按照自己的编写习惯调整一下源代码, 比如该放到 a 文件却放到 b 文件的符号就给它挪个位置, 比如某个函数只有一处调用, 那么就和调用方放到邻近的位置等等
有些源码文件没有阅读的必要, 比如工具函数等
源码文件可以通过一些手段预估它是否适合阅读, 比如我写了一个工具统计一个文件的注释行数占总行数的百分比, 百分比越高, 则内容应该越容易理解, 那么就优先看注释多的文件
任何项目都有应对各种现实问题而添加的特殊补丁, 如果读者自己没有这些现实问题, 这部分的代码就可以直接删掉, 这样整体链路会更清晰和方便理解 典型的比如, 你是 macOS 用户, 然后服务器肯定是 Linux 系统, 那就把源代码中 windows 相关的部分都删了
源码包含两种知识, 借用面向对象的术语, 可以叫公共知识和私有知识 公共知识就是业内通用的知识, 私有知识就是源码作者自己发明的一些文件数据结构、处理算法 比如, ELF 文件格式是公共知识, 而 Go 独有的 go object file, 就是私有知识
公共知识, 源码中往往不会进行说明, 因为源码作者自己肯定知道, 同时他也不会从读者角度去考虑进行说明, 所以读者自己要识别出源码中使用了这部分公共知识并从“课外”学习
公共知识的特征:
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.