Linus曾说过,Read The Fucking Source Code!
但是个人感觉读源代码是一个很痛苦的过程,最近在看Java多线程,看到JUC,涉及到不少源代码,有些单单一个类就有数百上千行(虽然说有很多是注释),有时看看就看不下去了……如何克服看源代码的急躁(急于求成),培养阅读源代码的耐心(遇到不懂的英文或难理解的地方,容易放弃)……
大家是有什么阅读源代码的好方法,都读过什么源代码,花了多少时间?求分享经历!
之后打算,了解下Android的源码,有相关经验的也可以分享……
Linus曾说过,Read The Fucking Source Code!
但是个人感觉读源代码是一个很痛苦的过程,最近在看Java多线程,看到JUC,涉及到不少源代码,有些单单一个类就有数百上千行(虽然说有很多是注释),有时看看就看不下去了……如何克服看源代码的急躁(急于求成),培养阅读源代码的耐心(遇到不懂的英文或难理解的地方,容易放弃)……
大家是有什么阅读源代码的好方法,都读过什么源代码,花了多少时间?求分享经历!
之后打算,了解下Android的源码,有相关经验的也可以分享……
python 的读过 tornado、requests,其他的用到什么读什么,C++ 的读过 xpdf,不开源的就更多了。。
第零步 —— 准备好你本次的阅读目的
一个项目,特别是上万行的代码,你是不可能一次读完的。带着目的读代码,而不是翻代码。
如果你是要修改一个功能,这样明确的目的就非常好。
如果不是,也请列一个提纲,比如今天读懂代码组织方式,明天读懂架构,后天读懂功能A 等等。
你可以用剥洋葱的方式一层层往里读,也可以直接切一刀。但是请不要翻代码,这样永远都读不懂。
第一步 —— 把代码运行起来
读代码之前请一定要让代码能运行起来,读 usage,读 API 文档,把握代码的主要功能和功能入口。如果你连程序是干嘛的都不知道,怎么读代码?
第二步 —— 找入口点
根据上一步你了解到的功能,选一个最简单的(比如 xpdf 有 GUI,有 pdftopng, pdftohtml, pdftotext,显然难度是下降的)程序,或者 API。找到它的源码位置,从它开始读。而像 tornado 的文档直接就有 API 到代码的链接,就简直太完美了!
不过,像 tornado 这样的异步架构,你可能找不到它的主循环,这时候找一个主事件处理 callback 就可以。
第三步 —— 观察数据流
好,假设你在第二步选好了要读的 main 函数或者主循环。不要着急读代码,首先看看 argv 在 main 函数中是怎么解析的,传递给了谁,谁输出了结果。主函数是怎么拿到请求的,谁处理了请求,最后输出的是哪个变量。
第四步 —— 只看函数,不看逻辑
跟着数据流,看它经过的函数,不要看逻辑,只看函数。猜,它是干嘛的。如果猜不出,跳到函数定义,看函数头注释,看接受的参数。但是记住只跳一层,不要看代码逻辑。
如果你是在剥洋葱,找个小本本记下每个函数的功能,明天请从最主要的那个函数开始看。如果你有着明确的目的,猜哪个函数和你需求相关的,进入那个函数继续看。
GOTO 3
因为很重要,再说一次,在认识所有的函数之前,不要读代码逻辑!除非:一、你已经找到你需要修改的地方;二、它是这个程序的最主要的功能算法。而这样的代码,整个程序往往只会有一处。
带着问题去读……(以前有个英语老师就是很喜欢说这句话,以至于现在我回想起这句话还是会响起她的声音)
就是,假如是有issue的项目,那么带着其中的一个或几个issue来阅读,看看到底是怎么一回事。说不定还能帮忙fix一下呢。
如果没有,你可以去找一下相关功能的是在哪里实现的,是如何实现的。
足兆叉虫已经说的很好了,这里补充一些自己有时候会用的方法:
1. 看项目的概要文档(API文档最好不要一开始就看,除非必要)搞清楚代码的目录结构和模块功能;
2. 看项目的测试案例,了解各模块的用法;
3. 看不懂的地方,google查找相关的文章,或许已经有人分析过相同的模块;
4. 如果是c++, 快速画类图和时序图(不求完备,只为了再次看的时候用来查询);
我是做Android驱动的,说说我读vold源码的历程吧。
其实刚开始我是拒绝的,后面SD卡遇到了一个获取卷标乱码的问题,虽然可以在上层规避,但是我还是想弄清楚到底哪儿出了问题,于是毅然啃起来源代码。主要是Android中用于获取磁盘分区信息的可执行文件——blkid的源代码。
跟很多答案一样,我发现带着问题去阅读源代码效率要高得多,边看边打log调试,很快就弄清楚了整个模块的工作流程,也定位到了问题,并修复了这个bug。还是蛮有成就感的。
总结就是:
最好是带着问题去看源代码,这样效率真的很高,否则的话,容易变成翻代码。
laravel(队列部分)。
一个很深切的感受就是:laravel框架是典型的对基础应用友好,对高级开发苛刻。入门指南很清楚明白,但是开发框架本身的指南就完全没有了,甚至于部分注释自动生成的API都不完全的。想给laravel写一个扩展,必须深入到框架源码中做一番研究,没有商量。
以上的话虽然不好听,可意外的是,这些话还真的不是黑laravel。因为laravel迭代速度快,并且使用方式的自由度实在是过大。在这种情况下,与其抽出精力写一个半生不熟的文档,反而是干脆不写,省出时间来优化代码,允许开发者方便的深入框架,在工程上更加合理。
这件事有一个反例就是WordPress Codex。开发WordPress时看着Codex上那些陈旧和信息不充分的页面,有时颇有“还不如没有更好”的感受。
而laravel的代码本身:
在开发者识读和扩展的便利性上,laravel的代码是可圈可点的。
我对读的建议就是:代码只读最优秀的。不优秀的代码,要么原样使用,要么小修小补使用,要么干脆重写。
读最优秀的代码犹如与最顶尖的人才共事。这会让自己写代码的时候,都不好意思写的没有档次。这种逼迫对自己水平的提高极有用处。
代码,要读就读laravel这样的。
什么时候读、怎么读呢?最好是逼到有什么非读不可的需求的时候再读,读的时候一切以完成需求为目标,效率杠杠的。没有需求就去用别人的代码做点什么有意义的事情,需求迟早会冒出来的。
参阅:我扩展laravel的一个github项目《献给虚拟主机 Laravel 用户:全功能 MySQL 队列驱动器 L4mysqlqueue》