如何高效阅读一个项目
经验分享 - 如何高效阅读一个项目
对于一个程序员来说,阅读优秀的项目代码是一个学习的好方法,但对于项目越大,阅读的难度也越大。
先说一个最“笨”的方法,初学者在接触到项目代码后往往从入口函数开始,一行一行地往下看,这种方法不适合规模较大的项目,阅读的效率非常低。
下面介绍另外几种的方法。
既然是阅读好的项目,那怎样的项目才算好?
最优秀的不一定是好项目,但好的项目一定是适合自己的。
要求:
- 项目所使用的编程语言最好是自己掌握的,这里强调的是掌握,即使不熟悉也没关系。先大概浏览一下项目,观察里面涉及到的技术,如果里面很多内容都是陌生的,那这个项目恐怕未必适合。即先不求理解,但起码能看懂七、八成字面意思。
- 项目中所涉及的理论知识已经大概掌握。掌握其中涉及的核心理论,在阅读过程中对理解有很好的帮助。因此在看项目之前,如果不了解相关理论,建议去查询一下,只需了解大概即可。
-
要求程序是可执行的。阅读的项目最好是能够运行起来的,一来可以直观地展示项目代码修改后程序所发生的变化;二来可以让程序测试不同的demo数据;三来可以使用gdb进行调试。如果只靠眼睛去阅读代码,大脑中想象程序运行效果,理解起来会变得抽象和不切确。
-
明确阅读代码的目的。提升自身编程能力的确是阅读代码的一个目的,因此不少人喜欢一行一行地去阅读代码,充分理解每一个语句的效果,每一个变量的含义。但是这种阅读的效率同样太低,过于斟酌细节,就无法快速掌握程序的整体流程,造成理解的片面,加大阅读难度。况且当项目的不同变量之间的关系比较复杂,多个代码段之间也存在数据流通时,逐行阅读来理解所花费的精力是巨大的。阅读代码,更重要的是理解其中的“设计”,这种设计可以是算法的设计,也可以是项目架构上的设计,或者模块划分上的别出心裁等等。而设计主要是在宏观上去把握,实现的方法有很多种,关键是其中的”逻辑可行性“,即这个方法来实现这种设计是否行得通。
-
有了明确的目的之后,就可以正式开始阅读项目了,注意在阅读的过程中不要被各种细节拖进深渊之中,要懂得去理解项目中好的设计。结合理论去分析项目的各个模块,大概理解程序执行的流程。如一个编译器程序,执行流程可以是词法分析->语法分析->语义分析->中间代码生成->中间代码优化->目标代码生成。
在宏观上去理解程序中各个模块的划分,把握主要流程。 -
阅读单个模块。项目的模块一般指功能比较专一,联系紧凑的一组代码。阅读单个模块,可以更集中注意力,减少程序其它无关代码的干扰。但这个方法有2个受限的情况,一是该模块过于复杂,如果一个模块本身就很复杂,那阅读的效率也不高;二是多个模块之间联系比较紧密,单个模块地去阅读容易会造成理解上的中断。比如编译器项目中阅读中间代码优化模块,就必须对中间代码生成模块有所了解。
-
对于阅读复杂的项目,往往需要结合多种阅读方法,时而逐行阅读、时而单个模块阅读。但我主要推荐的是结合测试集来阅读代码。一个程序具有多种的功能,每种功能对应一个测试集,通过gdb之类的调试工具观察程序在处理某个测试数据时的逻辑流程。
这种做的好处有很多。令一个测试数据集对应程序的一种功能,便可通过选定某种测试集配合gdb调试,来观察程序执行某特定功能时的逻辑处理流程。在这个过程中,可以忽略程序跳过的代码(即无关代码),着重理解被执行的代码,并且这些代码所实现的功能(对应测试数据集)我们是知道的,不需要另外去猜测。这种“已知结果倒推过程”的方法比”已知过程推导结果“的方法高效许多,能更快地理解代码设计的缘由,其中的差别就像求解一个问题的答案和将答案带入问题验证。同时删减测试集的规模可以调整调试时的难度。 -
注重逻辑可行。前面通过测试集调试代码来阅读项目,此时执行的代码流程更加简练紧凑,我们应该把注意力放在程序实现该功能时的逻辑处理部分而非代码上,即程序通过什么方法实现了该功能,在阅读代码的过程中不断加深理解,自己能否同样想到一个逻辑上可行的方法(即算法),同时留意程序所采用的数据结构。这样下来,可能不需要从头到尾地阅读,自己就已经理解实现的方法了。
下面再说一点”模仿“一个项目的经验
对于提高编程能力,我认为阅读代码不是最高效的,而是编写代码。因此阅读好项目的同时,也要学会动手写项目。刚开始可以先模仿,切记模仿的过程不是一行一行代码地复制,这样能真正掌握的知识不多,编程能力的提高也有限。就像背书,过几天可能就忘光了,或者变一下题目就不会了。
读项目,是理解其中的设计与方法。模仿项目,则是将学到的设计和方法再自己用代码写一遍。
测试集可以用来辅助读项目,同样也可以用来辅助写项目。写项目的时候,先从最最简单的功能开始实现,要求能够跑起最简单的测试数据,这时候写出来的程序是不完整的、残缺的,但是没关系,让它先能够运行起来,这很关键,至于为什么,道理和阅读项目的理由差不多,尤其是debug的时候,调试何尝不是一个加深理解的方法呢。能成功运行一个测试集,之后再往上加,使它能够支持更多不同类型的测试数据集。
刚开始“模仿”项目,可能有点无从下手,或者思路偶尔中断,这时可以回去查看一下原项目,但是尽量多地自己写,尽量少地查看原项目。把自己想到的尽量写出来,和原项目不一样也没关系,甚至是有利加深理解,编写的过程切记不要怕之后可能要重新修改,多改多写才能进步。
初期一边自己写写,一边参考一下原项目,在实现了几个功能后,此时就可以几乎不看原项目,按照自己的流程走了,将此前阅读项目时体会到的设计和方法自己实现一遍,在这个过程中甚至可以自行优化,发现其中的不足;而如果遇到瓶颈,而说明此前理解不够透彻,有所偏差,自己重新在思考一遍逻辑可行性。总之这样下来,原项目的绝大多数方面都被考虑了一遍。
在实现每个功能的时候,debug很有用,这能加深我们的理解,更加游刃有余地处理各种情况。因此多改写,多调试,这在模仿项目过程中至关重要,甚至是提高编程能力的核心步骤。
调试过程中可能会对于某些特定变量的含义有疑惑,此时可以只观察该变量 赋值与引用 语句来分析其含义。
如a=lineno, 对a的赋值表示该变量表示行号,另外error(a),对a的使用表示error需要传入一个行号信息。当一个全局变量跨文件使用时,这样分析能较好地捋清思路。