如何阅读源码?
保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/39/ )。
本回答将按照下面的章节体系进行:
1 我为什么阅读源码
2 阅读源码的好处
3 阅读源码的困难
4 阅读源码的步骤
5 阅读源码的方法
1 我为什么阅读源码
我开始阅读源码是在进行互联网开发的第八九个年头。在此之前,我做过校园网站,接过网站开发的私活,进行过理论算法相关的研究,也设计开发了许多系统。我对我做过的系统都比较有信心,它们也都运行的不错,但是一个疑问却在我的心头逐渐浮现:我的架构和世界最优良架构之间的差距到底有多大?
阅读开源项目的源码能给我答案。
许多优秀的开源项目历经数千开发者的数万次提交,被数亿用户使用。这些项目从可扩展性、可靠性、可用性等各个角度考量,都是十分优良的。通过阅读这些项目的源码能让我找到自己在软件设计和开发上的不足。
于是我开始了我的源码阅读计划。
2 阅读源码的好处
阅读源码的好处很多,而且已经成为共识。光靠铺天盖地的源码阅读活动就能感知一二,虽然我觉着那些活动都太过浮躁,主要是个噱头,学不到啥。
但是不可否认,阅读源码的好处极多,包括但不限于:
- 透彻地理解项目的实现原理
- 接触到成熟和先进的架构方案
- 学习到可靠与巧妙的实施技巧
- 发现自身知识盲点,提升自身知识储备
所以,我有些后悔,我觉着我应该更早地开始源码阅读。我推荐进行源码阅读的时机是:学会编程语言的基本知识,并做过少量项目之后。
我们知道,学编程的过程中在不断接收新的知识,进步很快。刚开始做项目时,进入实践领域,进步很快。然后就到了平台期,可能几年下来都是重复的增删改查,毫无进步。这段平台期实际是进行源码阅读的良好时机,能让你的技术持续进步。
3 阅读源码的困难
当我们阅读一份源码时,需要面对的困难通常有:
- 难以归纳的凌乱文件
- 稀奇古怪的类型组织
- 混乱不堪的逻辑跳转
- 不明其意的方法变量
- ……
所以很多人即使知道阅读源码的好处,也坚持不下来。就因为以上困难难以克服。
而阅读源码的难,是正常的。
3.1 时间维度带来的困难
从时间维度上看,每一个优秀的工程项目都经历了从雏形到成熟的曲折演化过程。而整个过程都会被映射到一个时间点上,肯定很难。
于是有人提出了“阅读源码时,从第一次提交开始阅读”的主意。我要说一下,这是错误的!
这是一种纸上谈兵式的错误,提出这种方法的人肯定没怎么读过源码。事实上,我也有过这种想法,然后在实践中很快被抛弃了。
如果一个项目只经过了几次提交,这种方法获取可行。而一个优秀的通常有几千上万次提交,将这几千上万次提交都读完,工作量要比把当前最新版本的代码读完难的多得多!因为其时间维度的复杂度比空间维度复杂度大得多了。
我用下面的图片展示了项目发展的过程,一个项目从版本1到版本n,逐渐完善。版本1一般是最简单最基础的,但是,要想从版本1读起,一直读到版本n,可能要阅读几千个版本。难度极大,远不如直接去读版本n。
还有,许多项目的第一次提交并不是只有几行代码的init项目,往往第一次提交就是几百个类。而且,初期的代码组织还比较混乱。毕竟,作者也不知道该项目能火,往往比较随意。
更别说,历史提交中还夹杂很多的Bug、回退、依赖包升级等等。想要把每次Bug、回退、依赖包升级所产生的历史背景都搞清楚,这几乎是不可能的任务。
3.2 空间维度的困难
每一个优秀的工程项目都凝聚了众多开发者的缜密思维逻辑,而这些逻辑都被投射到了平面的代码上。这使得阅读源码的过程成了逆推开发者思维逻辑的过程,显然,逆推是很难的。
不过,这方面的困难真有解决方案:详细了解开源项目的功能,然后自己琢磨该如何实现。
这样,就将“逆推”的过程转化为了“正向推导+验证”的过程,这样就相对简单了。
但无论如何,阅读源码总不会太简单。于是有人说读懂源码比编写源码更为困难,想必也是有一定道理的。
4 阅读源码的步骤
阅读源码推荐按照下面的步骤进行:
- 了解项目的背景。这相当于了解了项目的需求。
- 充分了解项目的功能,并熟练使用。我们说过,将“逆推”的过程转化为“正向推导+验证”的过程是阅读源码的一个重要方法。而了解项目的功能是这个方法的基础。
- 调试代码。通过断点调试,掌握整个代码的流程走向、主次关系、依赖关系。
- 划分源码。根据每个包、模块的功能不同,将源码划分为几个部分。
- 由底层到上层,逐个击破。先阅读不依赖其他模块的,或者依赖其他模块比较少的基础模块。然后逐步上移,完成整个项目源码的阅读。
- 横向总结。在由底层到上层阅读完成后,横向以功能点为维度串联源码的实现逻辑。
一般情况下,一个项目的源码要在3~4个月左右读完。否则,可能读到后面的,已经忘记前面的功能了。
当然越快越好,但考虑到我猿们还要加班,时间太短了不太现实。
5 阅读源码的方法
有人说读懂源码比编写源码更为困难,不无道理。而源码阅读和软件开发一样,是一个非常综合的能力,没有一个万全之法。但有很多不错的方法。
例如一些常用的方法:
- 调试追踪:多数情况下,当我们对某些变量的含义产生疑惑时,借助开发工具的调试功能直接查看变量值的变化是一个非常好的方法。而且该方法还能指引代码逻辑的跳转过程,对于理解源码极为有用。
- 归类总结:优秀的源码都遵循一定的设计规则,这些规则可能是项目间通用的,也可能是项目内独有的。在源码阅读的过程中将这些设计规则总结出来,将会使得源码阅读的过程越来越顺畅。
- 上下文整合:有些对象、属性、方法等仅仅通过自身很难判断其作用和实现。此时可以结合其调用的上下文,查看对象何时被引用、属性怎样被赋值、方法为何被调用,这对于了解它们的作用和实现很有帮助。
- 类比阅读:如果存在实现某功能的两条或者多条路径,可以类别阅读,找出他们处理逻辑的不同。
还有很多方法,不再一一介绍。因为没有实在的源码案例,光介绍显得很浮。
如果大家真的决定阅读源码,开始提升自己架构能力和编程能力的新阶段,可以阅读《通用源码阅读指导书——MyBatis源码详解》。
是一本以MyBatis源码为材料,详细介绍源码阅读相关方法和技巧的源码阅读指导书籍。
该书以实际开源项目MyBatis为例,详细介绍了源码阅读的经验和方法。在源码阅读中,透彻分析了相关的背景知识、组织方式、逻辑结构、实现细节。在本书的讲解中,不漏过每一个类,不跳过每一个难点,做到深浅一致。并对这些源码阅读方法进行了进一步的总结整理。
但我保证,只要你读完一个项目的源码,就会收获巨大。
最后,用书籍前言中的一句话结尾。
可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。