引言
阅读代码是程序员的基本技能,同时也是软件开发、维护、演进、审查和重用过程中不可或缺的组成部分。本书首次将阅读代码作为一项独立课题,系统性地加以论述。本书引用的代码均取材于开放源码项目——所有程序员都应该珍视的宝库。
本文围绕代码阅读,详细论述了相关的知识与技能。“他山之石、可以攻玉”,通过仔细阅读并学习本文,可以快速地提高读者代码阅读的技能与技巧,进而从现有的优秀代码、算法、构架、设计中汲取营养,提高自身的开发与设计能力。
代码阅读有自身的一套技能,重要的是能够确定什么时候使用哪项技术。本文使用多个现实的例子,向读者展示如何区分好的(和坏的)代码,如何阅读,应该注意什么,以及如何使用这些知识改进自己的代码。
养成阅读高品质代码的习惯,可以提高编写代码的能力。
有一扇窗,从未打开,却要永远关闭;
有一些人,确实存在,我们却无缘相见;
有一种生活,还没有到来,我们却已永远离开。
好代码:美妙如音乐
好的程序就如同好的音乐一样,它们完成得那么巧妙,那么完美,体现出完全没有词藻的美丽。就如同好的音乐能够改变你对人生的看法,让你重新审视你的生活,和多年前的人进行跨时空的交流一样。
作为软件开发人员,好的程序,所能够带来的感受,丝毫不逊于音乐给你带来的冲击。
更为难得的是,这些宝贵的程序往往并非由”权威人士”、”享誉海内外的专家”所编写,它们是由一个个普通的程序员写就。这些程序员和读者没有什么不同。虽然这些程序员并非叱咤风云的人物,但专业造就了专家,长时间集中在某个领域中,就能够创建出所有程序员都应该珍视的财富。
就如同古代的米开朗基罗,相比于当时那些声名显赫的主教、贵族来说,他是多么的微不足道,但时至今日,那些人和他们的的名字都随风飘逝,昔日的荣光都随时间而暗淡,而米开朗基罗的名字却铭刻在大多数甚至是普通人的心中,许多人的脑海中都能浮现出那些完美的雕塑—“大卫”、”创世纪”。这分荣耀在文艺史上可能无人能及。
万事万物都是从量变到质变的
我们是程序员。
我们的工作(许多情况下,还有我们的激情)是通过编写代码来创造新的事物。PRD、UED 稿、大量的图示、详尽的项目进度表、一堆堆厚厚的设计十文档并不能满足用户的需求。这些都是愿望,设计,表达出我们希望实现的东西。我们只有通过编写代码才能交付真正满足用户需求的东西:代码才是现实的、实在的、踏实的。
恐怕,没有哪个伟大的小说家,从未读过其他人的著作,没有哪个伟大的画家,从未研究过他人的绘画作品,没有哪个技术熟练的外科医生,从未观摩过同等事如何动手术,没有哪个机长不是首先在副驾驶员的位置上观看如何实际操作的。
由此及彼地类比,我们可以容易理解到:编写伟大代码的方式是阅读代码,阅读大量的代码:高品质的代码、低品质的代码; 汇编语言代码、C 代码、C++代码、Java 代码、PHP代码、Go 代码、Kotlin 代码、TypeScript 代码、Haskell代码、Lisp 代码,千里之外的陌生人所写的代码,以及我们自己上周刚刚编写的代码。因为,如果不这样,我们就会不断地重做别人已经经完成的工作,重复过去已经
发生过的成功和错误。
阅读代码
我们所观测到的不是自然本身,而是大自然在我们所用的观察方法下展现出来的特性。
—Werner Heisenberg
通过正确地代码审查,可以发现 90%的软件错误。
程序员花费在软件上的时间,超过一半是在阅读、维护别人的代码上。
代码阅读成为当今软件工程师的一项基本技能。此外,阅读实际的、编写良好的代码,可以更加深人地了解如何构造与编写重要的系统,仅仅编写小型的程序学不到这种能力。
程序员的工作中,很大一部分内容是阅读、理解、以及修改最初的(自己写的和别人写的)代码。遗留代码持续不断、不可避免的累积,对软件重用的强调,软件行业中人员的高流动性等等因素,都造成了工作复杂性极高、挑战极大。
要养成经常花时间阅读别人编写的高品质代码的好习惯。
就像阅读高品质的散文能够丰富词汇、激发想像力、扩展思维一样,分析设计良好的软件系统的内部结构可以学到新的构架模式、数据结构、编码方法、算法、风格和文档规范、应用程序编程接口(API),甚至新的计算机语言。
阅读高品质的代码,还可以提高您编写代码的水准。
代码可读性
我很遗憾地告诉大家,就在最近,我再次查看了我的程序(质因子和井字游戏),它们没
有任何形式的注释或文档。
I regret to report that I’ve just recently looked again at my programs for prime factors and tic-tac-toe, and they are entirely free of any sort of comments or documentation.
—Donald E. Knuth
在编写程序时就应该考虑到使之易于阅读,并且,不管程序是否容易阅读,人们都需要去阅读它们。
写可读性良好的代码,于人于己,都是功在当代,利在千秋的大好事。
重用
阅读代码也可能是为了寻找可供重用的元件。但不要期望太高。
代码的可重用性很诱人,但难以掌握。降低期望就不会感到失失望。
编写可重用的代码很困难。
多年来,只有比较少的软件经受住时间的考验,在多种不同的解决方案中被重复使用。软件部件一般要经过逐渐地扩展,并重复改写以适用于两个或三个不同系统之后,才会成为可重用的部件。
专为特别的目的而开发的软件很少满足这些条件。实际上,根据软件成本模型(software cost model),编写可重用的软件可能会增加50%的开发工作量。
阅读代码的格言
- 第一次分析一个程序时,main 是一个好的起始点。
- 要养成,经常花时间阅读别人编写的高品质代码的好习惯。
- 要注意并重视代码中特殊的非功能性需求,这些需求也许会导导致特定的实现风格。
- 在寻找bug时,请从问题的表现形式到问题的根源来分析代码。不要沿着不相关的路径(误入岐途)。
- 要充分利用调试器、编译器给出的警告或输出的符号代码马、系统调用跟踪器、日志机制、包转储工具和消息侦查程序,定位bug的位置。
- 从特性的功能描述到代码的实现,可以使用关键词来搜索相关代码。
- 重构时,从一个能够正常工作的系统开始做起,并确保结束时,系统能够正常工作。一套恰当的自动化测试用例(test case) 非常必要。
- 在上手一个新的软件系统时,要注意,系统是由很多部分组成的,不仅仅只是执行语句。还
要注意分析以下内容:文件和目录结构、生成和配置过程、用户界面和系统的文档。 - 代码阅读有许多可选择的策略:自底向上和自顶向下的分析、应用试探法和检查注释和外部文档,应该依据问题的需要,尝试所有这些方法。
- 创造性的代码布局可以用来提高代码的易读性。可以使用空格、临时变量和括号提高表达式的易读性。可以用好的缩进以及对变量名称的明智选择,提高编写欠佳佳的程序的易读性。
- 编写、阅读代码时,要养成添加注释的习惯。
- 天下大事,必作于细;天下难事,必作于易。解决困难的代码要从容易的部分入手。
结语
夕阳西下的黄昏,泡上一杯茶,合上笔记本,揉下坐久了的老腰,舒展双臂,眺望窗外的远山。这是不是有一些”采菊东篱下,悠然见南山”的意境呢?只不过陶渊明种的是菊花,我们播种与收获的是代码而已。