如何阅读一份源代码?
阅读源代码的能力算是程序员的一种底层基础能力之一,这个能力之所以重要,原因在于:
- 不可避免的需要阅读或者接手他人的项目。比如调研一个开源项目,比如接手一个其他人的项目。
- 阅读优秀的项目源码是学习他人优秀经验的重要途径之一,这一点我自己深有体会。
读代码与写代码是两个不太一样的技能,原因在于“写代码是在表达自己,读代码是在理解别人”。因为面对的项目多,项目的作者有各自的风格,理解起来需要花费不少的精力。
我从业这些年泛读、精读过的项目源码不算少了,陆陆续续的也写了一些代码分析的文章,本文中就简单总结一下我的方法。
先跑起来
开始阅读一份项目源码的第一步,是先让这个项目能够通过你自己编译通过并且顺利跑起来。这一点尤其重要。
有的项目比较复杂,依赖的组件多,搭建起一个调试环境并不容易,所以并不见得是所有项目都能顺利的跑起来。如果能自己编译跑起来,那么后面讲到的情景分析、加上调试代码、调试等等才有展开的基础。
就我的经验而言,一个项目代码,是否能顺利的搭建调试环境,效率大不一样。
跑起来之后,又要尽量的精简自己的环境,减少调试过程中的干扰信息。比如,Nginx 使用多进程的方式处理请求,为了调试跟踪 Nginx 的行为,我经常把 worker 数量设置为1个,这样调试的时候就知道待跟踪的是哪个进程了。
再比如,很多项目默认是会带上编译优化选项或者去掉调试信息的,这样在调试的时候可能会有困扰,这时候我会修改 makefile 编译成 -O0 -g,即编译生成带上调试信息且不进行优化的版本。
总而言之,跑起来之后的调试效率能提升很多,而在跑起来的前提之下又要尽量精简环境排除干扰的因素。
明确自己的目的
尽管阅读项目源码很重要,但是并不见得所有项目都需要从头到尾看的清清楚楚。在开始展开阅读之前,需要明确自己的目的:是需要了解其中一个模块的实现,还是需要了解这个框架的大体结构,还是需要具体熟悉其中的一个算法的实现,等等。
比如,很多人看 Nginx 的代码,而这个项目有很多模块,包括基础的核心模块( epoll 、网络收发、内存池等)和扩展具体某个功能的模块,并不是所有这些模块都需要了解的非常清楚,我在阅读 Nginx 代码的过程中,主要涉及了以下方面:
- 了解 Nginx 核心的基础流程以及数据结构。
- 了解 Nginx 如何实现一个模块。
有了这些对这个项目大体的了解,剩下的就是遇到具体的问题查看具体的代码实现了。
总而言之,并不建议毫无目的的就开始展开一个项目的代码阅读,无头苍蝇式的乱看只会消耗自己的时间和热情。
区分主线和支线剧情
有了前面明确的阅读目的,就能在阅读过程中区分开主线和支线剧情了。比如:
想了解一个业务逻辑的实现流程