唐纳德·克努特甚至引入了文学编程(literateprogramming) 编程范式。 编程与写作有相同的理念:表达我们的想法 。 还记得你在学校是怎么学习写作的吗?我们的写作能力来源于从小学开始直到现在的大量的文本阅读。 多年以来,我们阅读了不同难度的伟大作家的作品,并练习了多种写作技巧。

和读书一样,有意地阅读代码可以帮助程序员加速成长,尤其是对中级(intermediate)程序员而言。

如果目前你不能理解某些特定的代码片段,这意味着你有个知识缺口(knowledge gap)。 把代码放到一边去,试着读一些相关的书、论文或其他文档,当你更有信心时再回来接着读代码。 我们总能在一个模式中取得进展:读(代码、书、论文),写,更多的读,更多的写。

如何读源码

《How to read a book》 是一本指导人进行明智地阅读的书。作为初学者,我们值得投入时间和精力去思考我们应该如何阅读代码。 阅读代码不是件容易的事。 光是阅读源码是不够的,你要试着去理解他人的设计和想法。

预先准备

为了更有效率地阅读代码,你需要提前在手边准备这些东西:

  • 一个你可以熟练使用的编辑器。你需要拥有快速搜索关键字或变量名的能力。 有时你需要查找函数的引用和定义。和你的编辑器相处融洽些。 为了更加有效率,试着学习仅使用键盘操作编辑器。 这会使你专注于代码而不受打扰(译:指额外思考编辑器操作)。
  • 掌握基本的Git或其他版本控制工具的技能,这样你就能比较代码在版本间的差异。
  • 与源码有关的文档。文档可以为你的阅读提供参考,尤其是设计文档、编码规范等文档。
  • 具有一定的编程语言与设计模式的知识和经验。这对(阅读)大项目是强制性的。 如果你很了解一门编程语言,你也会了解关于源码组织与编程范式的最佳实践。 当然,这需要时间来积累。要有耐心。

流程与技巧

阅读过程不是线性的。你不会就那么一个接一个地读源文件。 相反,大多数时候我们会从顶到底地阅读代码。 下面是一些更有效率阅读代码的小技巧:

结合上下文阅读代码

当你阅读代码时,请持续提出问题。 例如,如果一个应用有缓存策略,一个好问题就是:如果键无效了会怎样?缓存中的值如何更新? 带着这些问题阅读代码,就是结合上下文。或者说因为你有了一个目标,你会变得享受阅读的过程。 你甚至可以自己做一些假设,然后在代码中寻找验证。

你有点像侦探:你想发现代码的真相,代码的逻辑,代码是如何像故事一般上下流动的。

把实例跑起来并与之交互

源码就像乐高积木,只是已经组装好了。 如果你想了解它们是怎么组装在一起的,你需要和它交互,有时甚至要把它拆开。 阅读同一模块的老版本同样有帮助。从Git中阅读版本差异,试着弄清楚特定的特性是如何实现的 (修改日志在这个场景很有用)。 举个例子,我发现Lua的第一个版本相当简单,这可以帮助我了解作者最初的设计理念。

Debug是另一种与代码交互的方式。试着在代码中加一些断点(或打印一些变量值), 然后弄明白打印到控制台中的所有输出。

如果你对代码了解比较透彻了,试着对代码做一些修改,重新build并把它跑起来。 最简单的方式是试着调整配置项,去看不同配置的运行结果。 之后你可以试着添加一些细微的特性。 如果这些特性对其他人也有用,你应该把代码贡献到上游。

了解数据结构间的关系

“糟糕的程序员担心代码,优秀的程序员担心数据结构和它们的关系。” -Linus Torvalds

数据结构是一个程序中最重要的元素。用笔或者你喜欢的其他工具画出数据结构间的关系。 这个图就是源码的映射。你会在阅读过程中时常参考这个图。一些工具比如scitools 可以用来生成UML类图。 (译:这个方法用在写代码中能节约翻Model声明文件的时间,推荐用纸笔,不占屏幕)

了解模块间的依赖关系与边界

大项目中会包含许多模块,一个模块经常只拥有单一职责。 这有助于我们减少代码复杂度,在适当的层级上做抽象。 模块的接口是抽象的边界,我们可以一个接一个地阅读模块。 如果你在阅读一个使用Make构建的C/C++项目,Makefile是了解模块间如何组织的好切入点。

边界本身也很有用。优秀的代码组织得很好,变量名与函数名的命名风格体现着可读性。 你不需要阅读全部源文件,你可以忽略不重要的或你熟悉的部分。 如果你确定一个模块是仅仅是为了被解析而设计的(just designed for parsing), 那么你已经大致了解了它的功能;那么你就可以跳过不读这个模块。 当然,这将大大节约时间。

使用测试用例

测试用例也是帮助代码理解的一个很好的补充。测试用例就是文档。 当你在阅读一个类时,试着把对应的测试代码一起读了。 测试用例能帮你弄清一个类的接口,和该类的典型用法。 集成测试用例可以让你顺着走过程序的整体流程,适合输入一些特殊值并debug运行。

点评

为什么不在花了不少时间阅读一个项目后,写一篇代码点评呢?就像写一篇书评一样。 你可以写下代码中好的和不好的部分,还可以记下你从中学到了什么。 攥写这类文章可以帮助你阐明自己的理解,也有助于其他人阅读源码。

一些好书

我发现阅读代码是一个远超我想象的广泛话题。没有系统性训练该技能的方法。 总而言之,不断练习,找到你自己的方式。下面是一些帮助你提升代码阅读能力的好书:

《DesignPatterns:ElementsofReusableObject-OrientedSoftware》

《CleanArchitecture: ACraftsman’sGuidetoSoftwareStructureandDesign》

《HowtoRead aBook:TheClassicGuidetoIntelligentReading》

个人经验:驱动我“专门读代码”的最大动机是好奇心,和小孩拆小物件为了看内部构造差不多。 学习OO设计模式,我建议阅读《HeadFirst 设计模式》 ,这本书超有趣,比四人帮那本删减了一些不常用的模式,但是你能轻松读下去。

阅读了解项目代码是参与(开源)项目的第一步,希望这篇文章能帮助你参与到心仪的项目中去。 这也可以帮助你在工作中了解同组同事的工作,而“了解同组同事的工作对工作有诸多潜在益处” 。 来吧,花点时间挑一个看上眼的项目(或者就读你手头的项目别人写的部分), 找到你最感兴趣的功能,读一读它是怎么实现的。