《代码整洁之道》ch5~ch9读书笔记
本周我阅读了本书的第5~9章节,进一步了解整洁代码需要注意的几个方面:格式、对象与数据结构、错误处理、边界测试、单元测试和类的规范。以下我将分别记录各章的阅读心得体会。
1. Ch5: 代码格式:简单而一致
一直以来,“让代码能工作”是我编程时的头等大事。但事实上,尤其是涉及到体量庞大、经常修改的工程代码时,代码格式才是重中之重。显而易见,一套整洁规范的代码格式能给软件的开发、测试和维护提供巨大方便,而随心所欲或不统一的代码格式则会大大增加代码的阅读难度,也会让使用代码的人质疑开发者的专业程度、职业态度。
代码格式的原则有许多版本,因不同团队的需求、喜好,以及不同语言的特性而定。书中介绍了一些普适的原则,比如逻辑上联结紧密的语句应该编写得较靠近,不同功能的函数间最好相隔空行,水平、竖直缩进对齐等。结合适当的变量命名,这些简单的原则足以使代码清晰明确。
作为一支团队,代码的格式规则更是务必一致,追求“如一人所写”的效果。本周我们组在组会上也针对代码格式进行了讨论,参考网上众多的代码格式规范,决定在下一次组会选定相关格式。
2. Ch6:对象与数据类型:仔细的抉择
对象和数据结构各有特点。对象包含众多行为信息,但隐藏具体数据和实现手段,添加新对象类型并不需要修改既有的行为,较为方便,但难以添加新行为。而数据结构包含数据信息,没有明显的行为,因而添加新行为到数据结构中较方便,但向既有函数添加新数据结构是困难的。
作为开发者,我们需要在这两者间进行权衡和选择。同时,还要考虑到保密性、隐藏细节、用户体验等等。在这一层面,整洁代码的要求就是结构之间划分清楚,不要混杂使用,同时尽量少地暴露技术细节。
3. Ch7:错误处理:逻辑的保护
这一章主要阐述的并非整洁,而是强固。一份整洁的代码,也应当具有合格的强固性,不让各种报错将程序逻辑搅成一团乱麻。这也是对代码可维护性的保障。
每当我们编写函数,总要考虑各种预期外的情况及处理方式。至今为止,我采用的处理方式基本都基于函数返回值,这样的方法较简单粗暴,但涉及到大体量的代码时显然难以测试,其返回值还可能对其他调用的函数造成逻辑上的干扰。本章中,作者建议我们使用不可控异常来替代返回码报错,并对异常发生的环境进行说明。这样能将错误处理隔离,且try-catch模块易于测试、记录和理解。
较普适的原则:不要返回、传递null值。在刚接触链表等C语言数据结构时,我就经常犯下传递、调用null的错误,并因此付出了成堆的时间和精力。在大型程序中,null值的传递若引发错误,带来的后果是毁灭性的:当程序的深处抛出NullPointerException异常,实在令人手足无措。
4. Ch8:边界:第三方代码使用之道
编程实践中,我们常常调用他人代码以实现功能,本章就介绍了在“借刀杀人”时可能引发的边界问题以及回避之道。学习和使用第三方代码库事实上相当困难,我们往往需要花很多时间来阅读使用文档、尝试编写测试代码、整合调试等。而采用编写测试来对第三方代码遍览和理解,即学习性测试,能很好地帮助我们上手。
正如作者所言,学习性测试是“免费”的,因为即便我们不这样做,也仍需要在使用时对第三方代码进行反复测试。同时,它不会影响现有工作,还能“与版本俱进”地增强我们对第三方代码的理解,保证整洁的边界。简而言之,想要用好一台机器,比起拆开它研究具体细节或只是翻翻说明书,还是实际上手使用,体验、了解其特性后将其投入生产,来得方便快捷。
5. Ch9:单元测试:简洁而不简单
生产代码与测试代码的分量,事实上旗鼓相当。说来惭愧,我至今几乎没有编写过测试代码,debug时也往往只是根据题目要求手动输入各种数据。本章中,着重强调了单元测试代码的重要性:它们让我们对写出的代码拥有确保其如愿工作的能力,让我们的代码可扩展、可维护、可复用。一段没有被测试代码覆盖的生产代码,往往没有人敢轻易调用和维护。但正因如此,测试代码的篇幅往往不逊于生产代码,对测试代码的管理也成为一大课题。
对此,作者的观点很简单:可读性为王。测试代码的变量命名应当比生产代码更为精确,并遵循F.I.R.S.T原则:Fast(快速运行)、Indepent(相互独立)、Repeatable(可重复)、Self-Validating(有布尔值输出)、Timely(及时编写)。整洁的测试代码是保证生产代码不腐坏的必由之路。
总的来说,本周我通过对这五章内容的阅读,对整洁代码的编写规范、内核理念有了更深的理解。鉴于本书之后的章节基本围绕系统、并发编程等我尚未掌握相关知识的领域,下周起我将暂时转读其他书籍,待相关知识有一定基础后,再继续此书的阅读。
参考文献:
[1] Robert C. Martin. 代码整洁之道. 人民邮电出版社, 2010.1.