我们经常需要主动或被动的阅读他人的源代码,理清各个类的作用及如何组织的,从而为修改或扩展原有的功能做准备。
尊重他人时间和自己时间的人是有教养的人,所以我们要表现的训练有素。对于高效阅读源代码,我们需要讨论以下问题:
-
阅读的目的是什么?
列出最初想弄明白的几个问题,在阅读的过程中不断划去一些问题,又新增一些问题,最终解决所有的疑问。 -
如何着手阅读或者有效的阅读顺序是什么?
肯定不是依次阅读每一份代码文件的方式,就像读一本书,这种视代码为毫无关联的个体的方法的缺陷是:当看了一定数量的文件后,这些类如何关联的问题
还不是很清楚,
费时费力
。
而是非线性阅读方式。从感兴趣的点进入,例如main函数,钻进又钻出,前进又后退;不时记录问题,做笔记,还需要查询工具书。
-
阅读过程中有哪些难题,如何解决?
个人感觉最大的问题是整体理解和记忆的问题,关键流程可能涉及几十个类,几十层调用关系,如何组织笔记的形式,达到好理解的效果。
因此,笔记的形式很重要,要重点记录以下2个问题:
- 一个功能的实现涉及了哪些类,被调用了哪些方法。(组织形式:UML的序列图 + 调用栈图)
- 一个类的职责是什么?(组织形式:UML的类图,或者文本笔记)
对于问题1,涉及实体多,线索复杂,一图胜千言,采用UML的序列图描述比较合适;此外,调试过程中的调用栈信息也非常重要,可以有效补充序列图对接口类的无力,可以在接口实现类记笔记写注释;
问题2比较简单,记录一个类职责可以使用UML的类图,甚至一个纯文本笔记即可。
下面谈谈我在阅读代码方面的实践:
绘制序列图,并添加标注(IDEA+SequenceDiagram插件)
- IDEA中安装“SequenceDiagram”插件,选择要阅读的方法,选择菜单“Tools”->”Sequence Diagram…",显示参数配置Dialog如下:
我们可以修改调用深度(call depth),不建议修改的非常大,否则,序列图包含的方法过多,生成的过细,不利于理解;
也不建议取消“Display only project classes”, 否则系统类也在序列图中被显示,类非常多,也不利于理解;
- 点击“OK”,生成序列图。有时在生成的序列图中有我们不想关注的类,可以通过上下文菜单“Remove Class XXX”的方式加以移除,不想关注的方法通过“Remove Method XXX”移除。
- 最终得到一个感觉整洁的序列图,我们可以在该图上进行标注(建议使用MarkMan工具),也可在笔记中在图片下面进行注释;
调用栈笔记法(动态阅读):
-
首先在源代码的感兴趣的某处设置一个断点,然后调试运行,例如:对Robolectric库的createApplication方法设置断点,获取调用栈如下:
image.png
- 按住Shift键,选中首尾两个方法,拷贝复制调用栈至笔记本;
- 阅读栈首的方法,在笔记本中添加注释;阅读完毕,选中当前方法,点击上下文菜单“Drop Frame”,则废弃该方法的frame,显示上一个栈方法的frame内容;
- 重复步骤3,整理后,可以得到整个程序执行的流程;
网友评论