总体上是这几点:
因为作者不一定太关心文档和注释:大多数人以正确实现为主要目标。所以要祈祷文档和注释是正确的,或者说大多数是正确的。
为什么不考虑没有文档和注释的情况?理由很简单,如果该项目不出名,作者也懒得维护,所以这些东西没有或不完善是很正常的。
So,挑著名一点的吧。
如果文档的质量足够高,那么文档中会记录代码每个部分,至少是关键部分的概览,并且还会关联到代码中的变量名。
如redis的backlog,实际上你可以直接通过grep在代码中找到对应的变量,到此就可以直接推测哪些函数在操作backlog,这样可以帮助你理解代码。
issue是用户对作者提需求,所以它至少可以解释为什么有这个功能。
但是能够提issue的人都应该是程序员,所以不论是作者还是用户都会讨论这个功能或bug的原因、设计细节。
比如redis用的epoll,是epoll_create而不是epoll_create1,原因就是兼容旧版本内核。
理由很简单,代码是复杂的,而人容易忘事情。
且不说读代码,就算是写代码。你今天写了一个函数,两周后你看到了,可能会在想“这是谁写的shit”。
不要相信手中的草稿纸会记录清楚这一切,因为首先纸笔写下的内容不方便修改,你可能要把一大堆东西写到一片很小的空间里,其次草稿纸就是帮助你理解一小段东西的,所以会很乱,所以第二天来了,就再也不想看了。
我曾经就很喜欢用草稿纸,结果是虽然写了很多,但是第二天几乎还是从头来。看看我用了多少草稿纸吧,里面的笔是一个参考物。
如何整理?首先利用电子技术,画一遍执行流程图,流程图旁边至少标记这是哪个函数做的事情,甚至你可以精确到哪一行。然后记下你今天研究的问题是什么,下一个要研究的问题是什么。如果有网页,记得也贴上。
如果还用上了断点,记得也保存一份断点。
因为读代码的时候,对整个项目的理解度不足,所以出现了一些难以理解的部分,可以考虑跳过。
怎么对不理解的内容留个印象?
首先,如果可以的话,看注释,或者利用关键词查文档,大概了解一下这是干嘛的。比如redis在复用rdb的时候,注释里说这是复制缓冲区。但是你不知道这个缓冲区是什么,也不知道其作用。查看了一下,操作了backlog,得知这个是复制命令的历史记录的位置。
/* Perfect, the server is already registering differences for
* another slave. Set the right state, and copy the buffer.
* We don't copy buffer if clients don't want. */
if (!(c->flags & CLIENT_REPL_RDBONLY))
copyReplicaOutputBuffer(c,slave);
但是还是不理解怎么办?没办法,你只能在整理的时候,在哪个文件的哪些地方有不理解的地方。
读代码的时候,你至少要明白整个程序最基础的部分,比如线程模型。然后还要找到一些明显很通用的东西,比如TCP连接的封装。如果你不读线程模型,那么你就不知道一个流程走完了,其接下来的步骤。
比如一个PING/PONG,收到了PING,然后设置写入回调来发送PONG。如果不理解线程模型,这个很可能就被忽略了。
当然还有一些东西要注意的,比如定时器,一定要知道作者的设计。我个人不建议redis的定时器的实现,因为它要做太多事情了!一个serverCron里面做的事情非常多,既要管cluster,还要管主从复制,还要更新自己的状态,还要负责重连!
当然我暂时没想明白什么样的定时器能够同时做到编写时容易,且读代码的时候也容易的。