阅读代码,对于一个程序员来说,是一项很基本而又很重要的能力。我也曾经跟很多新人谈过,“要多看代码,少写代码”,但是,因为阅读代码是件苦差,绝大数的程序员更宁愿写代码。其实写代码,和其它一些行业,也是有相通之处的。比如说,书法或者绘画,都是从临摹开始。写代码其实也是一样,从阅读别人的代码中,提高自己的鉴赏能力,你只有知道,什么是好的代码,什么臭的代码才有可能写出好的代码。而且阅读代码,还可以磨练人的意志和毅力。缺乏毅力的程序员,在这一关中纷纷落马,最后写了好多年的代码,写出的东西还是普普通通。
我也知道,很多程序员,一打开项目,看到一大堆的代码,头就大了。其实阅读代码还是有一定的技巧,掌握这些技巧可以减轻阅读的痛苦,当然,只是减轻,阅读代码还件苦事。但是,只有越过这一关,才有可能成为牛人,才开发出卓越的产品。不过,其实只要坚持下来,你就会觉得其实也没啥的了。
下面我就谈谈我十几年,在阅读代码的过程中,所积累下来的经验。
知识点
首先阅读代码,尤其是一个完整软件的代码,是要有一定的基础的,对于这个项目所涉及到的知识点,必须都有一个比较深入的了解。当然,这些知识点都是比较凌散的。
1、常见的算法和数据结构。比如递归、栈、树呀这些。不过这些在算法与数据结构这本书都有讲到。
2、设计模式,这个也是要知道的。关于设计模式,有一本专门的书来介绍的。
3、软件所涉及到的知识点。比如说,如果你要阅读 ALinq Dynamic 这个类库,就需要懂得词法分析,表达式树的构造这些知识点。
这些知识都是必须了解或者掌握的,否则阅读代码则无从谈起。
工作原理
花一点时间去了解软件的工作原理还是很有必要的。了解软件的工作原理,才能使得在阅读的过程中,抓住主干。正如我们要把发动机拆开来看,首先就得去了解它的工作原理一样。
比如说,你要阅读 JSON.NET 这个类型,你就要知道知道它的工作原理是把一个对象转换成一个JSON格式的字符串,或者把JSON格式的字符串转换成对象。
比如说,你要阅读 ALinq Dynamic 这个类库,你就要知道它的原理是将一条ESQL语句转换成一个表达式树,然后再去执行这个表达式树。
正如英语的阅读中,有粗读和精读,阅读代码也分为精读和粗读。所谓粗读,指的是在直接打开一个项目来阅读代码。精读,是在代码运时着的时候看。两者必须相互结合起来,才能有所侧重,而又不至于管中窥豹。但是在阅读代码之前,还有件很重要的事情,就是一定要熟悉软件的使用。
粗读
粗读的第一步,就是要借助 Solution Explorer 这个面板,去了解有那些文件,大慨会有哪些类,然后猜一下大慨会有些什么用途。当然,命中率和你的阅读经验很有关系,一开始猜错,或者无从思考,那也没关系,反事总有一个过程。
第二步就是要借助 Class View 这个工具,浏览一下命名空间里面的类,对于一些比较重要的类,再进一步看一下它里面包括的方法。哪些是重要的类?你觉得重要就重要。别担心猜错,看多了,命中率就高,这个纯凭经验。
对于我来说,这两步大慨是几分钟的事情。如果是新人,估计要多花点时间。
第三步就是开始正式阅读代码了。找到你要阅读的类,打开文件。(要阅读哪些类,这个是在前面两步就确定下来了),首先要看的是这个类都要有些私有变量,如果有必要,你还可以看看这些变量都在哪些方法中有调用到,VS 里有查看引用这个工具,但是我个比较喜欢用 Resharp 来看。再接着就是找到你觉得比较重要的方法来阅读。
然后再循环这三个步骤,直到自己觉得对于这个软件已经有了一个比较整体的认识了。
精读
精读,往往是带着问题去阅读的,为了解决某一个问题而去阅读。首先定为到你所要阅读的函数,然后设置断点,然后运行单元测试,什么?没有单元测试?如果真的没有,那代码估计也不是开源的。在命中断点后,如果没有命中,则要自己先写个单元测试去命中该断点,在命中断点后,通过 F10,F11,一边运行一边逐句地看,直到找到问题所在。在这个过程,你要注意的是:
1、堆栈,堆栈的调用是很重要的,通过堆栈的调用,你可以进一步理清各个方法的依赖关系。
2、变量的查看。对于某个变量有疑问,你可以在 Watch 窗口里查看。
熟能生巧,只要你肯花时间,肯定能总结出比我要好的技巧,以上都是我的一些经验之谈,希望能够对你有所帮助。