网络寻租

Programmer, Gamer, Hacker

如何阅读ruby源码

| Comments

最近阅读ruby源码非常顺手,这里整理一下阅读心得。

首先,为什么要阅读源码?因为几点:

  1. 用到的工具,一定要清楚实现,这样遇到问题能够处理。我在rails开发过程中,遇到一些诡异bug,调试了很久, 最后定位问题到了第三方gem上面。如果我对于它们的代码足够熟悉,可以很快定位到问题点,不需要浪费那么多的时间。

  2. 熟悉实现也是一个学习的过程。在看源码的过程中,我对于ruby的使用,如何做架构,都有了更深刻的认识。 写代码水平靠自己磨练,同时借鉴别人的代码也必不可少。很多知识和技巧自己悟出来就慢了,看别人的东西能够学到更多。

然后是重点:如何阅读。

读懂代码之前,我们要把项目的文档看一遍,知道如何使用它。 使用方法是项目的接口,熟悉它们,我们就把“未知”限定在项目的源代码之内, 对于理解源码有了坚实的基础。

之后我们要熟悉源代码的文件树结构。好的项目的文件安排是模块化的, 一个文件就是一个系统模块,ruby项目,一般是一个文件一个类。 这样一个复杂项目,就被切分成一小块一小块人能够理解的部分了。

在这里要停一下,回顾前面看到的文档,列出一些核心的入口, 然后基于这些入口,对于项目的实现提出一些猜想, 然后从这些入口出发,寻找对应的函数,一步步顺着方法调用,看对应的代码。

举个实际的例子。 我看sinatra源码的时候,关注了几个入口:get/post方法,如何被rack调用。 我会列出猜想:get/post代码应该是记录这些block到一个内部的数据结构中, 在代码里面,有针对rack做一个接口,调用的时候会去解析http请求,分发到对应的block里面。

然后我开始用findgrep寻找get,遇到函数调用,就用同样的方法一路看过去。 最后发现get方法实际上是给类创建了一个方法:#{verb} #{path},然后绑定它。 和我想的不太一样,并不是用一个数据结构。

然后我又去看rack调用过程,最后弄清楚了如何分发请求,如何调用请求,以及在执行中快速跳出, 并且学到了一个小技巧

在阅读源码的过程中,我弄清楚了:调用栈,数据结构,类架构,以及验证了阅读代码前的各种猜想, 通过了解里面一些看不懂的部分,学到了新的知识。整个顺藤摸瓜过程是非常愉快的。

对了,最后还有一点,记得记笔记。研究过程不记录就白研究了,下次你是绝对想不起来的。 我会把上面跟踪函数调用栈中遇到的核心区块记录下来,整理成一个执行过程文档, 下次需要的时候直接看这个文档就可以了。这是一个示例(当然只有我自己才看得懂啦):

1
2
3
4
5
6
7
8
9
call => dup.call! 复制自己一份。。
call!(env) =>
@request  = Request.new(env)
@response = Response.new
invoke { dispatch! } => route!
route! =>
base.routes 遍历
returned_pass_block = process_route(...) 
process_route 里面检查pattern是否匹配,返回对应的block

Comments