编写可读代码的艺术:末·代码块&测试


前言:上篇记录了如何改变程序的“循环与逻辑”来让代码更有可读性,包括几种技巧,这些技巧都需要对代码结构做出微小的改工,具体见这里。本文在前两篇的基础上,讨论第三部分,在函数级别对代码做更大的改动,以及第四部分,可读测试代码的重要性。


*第一部分:重新组织代码 *

如何编写可读代码

  1. 简化命名、注释和格式的方法,使每行代码都言简意赅。
  2. 梳理程序中的循环、逻辑和变量来减小复杂度并理清思路。
  3. 在函数级别解决问题,例如重新组织代码块,使其一次只做一件事。
  4. 编写有效的测试代码,使其全面简洁,同时可读性更高。

抽取不相关的子问题

在工程学中,主要研究的问题是关于把大问题拆成小问题,再把这些问题的解决方案放回一起。带代码中也类似,主要考虑的问题如下:
(1)针对某个函数或代码块,思考这段代码的高层次目标是什么?
(2)针对每一行代码,思考其是否为了直接目标而工作,其高层次目标是什么?
(3)若由足够的行数在解决不相关的子问题,抽取代码到独立的函数中。

也就是,把一般代码和项目专有的代码分开。使得最后大部分都是一般代码,通过建立一大组库和辅助函数来解决一般问题,剩下的只是让程序与众不同的核心部分。

纯工具代码

一些核心任务,大多数程序都会做,例如操作字符串、使用哈希表以及读/写文件。通常,这些“基本工具”是由编程语言中内置的库来实现的,对于没有的方法,需要自己来完成空白,也就是一个不相关的子问题,并应抽取到一个新的函数中。比如:读取文件函数:ReadFileToString()。

创建大量通用代码

在项目中广泛适用,常常有个专门的目录来存放这种代码(例如util),方便重用。通用代码有很多好处,完全从项目的其他部分中解耦出来,容易开发,容易测试,并且容易理解。

简化已有接口

创建自己的包装函数,隐藏不理想的接口。

过犹不及

为代码增加一个函数存在一个小的(却有形的)可读性代价,要注意适度,根据项目需求,付出代价满足得到成效才可以。

一次只做一件事

  1. 应该把代码组织得一次只做一件事情,如果所有代码纠缠在一起,对于每个任务都很难靠其自身来理解它从哪里开始,到哪里结束。
  2. 如果代码很长很难理解,尝试把其所做的所有任务列出来,其中一些任务可以很容易地变成单独的函数(或类)。其他的可以简单地成为一个函数中的逻辑“段落”。
  3. 难点:准确描述程序所做的小事情。

把想法编变成代码

简单技巧:用自然语言描述程序然后用这个描述来写出更自然的代码。所做的任务如下:

(1)像对着一个同事一样用自然语言描述代码要做什么    
(2)注意描述中所用    
(3)写出与描述所匹配的代码

具体的需要做到如下几点:
1、清楚地描述逻辑
2、了解函数库是有帮助的
3、把这个方法应用于更大的问题
(1)用自然语言描述解决方案
(2)递归使用(1)

少写代码

所写的每一行代码都是要测试和维护的,通过重用库或者减少功能,可以节省时间并且使代码库保持精简节约。可以通过以下几种方法少写代码:

  1. 保持小代码库
    (1)创建越多越好的“工具”代码来减少重复代码
    (2)减少无用代码或没有用的功能
    (3)项目保持分开的子项目状态
    (4)保持代码又轻又灵
  2. 删除独立的函数很简单,不让无用代码交织在项目中。
  3. 熟悉周边的库:每隔一段时间,花15分钟来阅读标准库中的所有函数/模块/类型的名字。
  4. 重用库有着很多好处,不仅节省时间,而且少写代码。在一个成熟的库中,每一行代码都代表相当大量的设计、调试、重写、文档、优化和测试。任何经受了这样达尔文进化过程一样的代码行都是很有价值的。

第二部分 测试与可读性

测试:任何仅以检查另一段代码的行为为目的的代码。

  1. 使测试易于阅读和维护。
    测试代码的可读性和非测试代码是同样重要的,可以把测试代码看做非正式的文档,它记录了真实代码是如何工作和应该如何使用。测试应当具有可读性,以便其他程序员可以舒服地改变或者增加测试。

  2. 测试原则:对使用者隐去不重要的细节,以便更重要的细节会更突出。

  3. 测试基本内容:对于这样的输入/情形,期望有这样的行为/输出。
    这个目的很多时候可以用一行代码来表达,使代码紧凑而又易读,让测试的表述保持很短还会让增加测试变得很简单。

  4. 让错误消息具有可读性:如果测试失败了,所发出的错误消息应该能容易跟踪并修正这个bug。

  5. 测试输入:选择一组最简单的输入,能完整的使用被测代码。

  6. TDD测试驱动开发
    测试驱动开发是一种编程风格,在写真实代码之前就写出测试。一般来讲,如果在设计代码时发现,这对测试来说是噩梦,那么就应该重新考虑这个设计。

如表所示为可测性差的代码的特征,以及它所带来的设计问题:

特征 可测性的问题 设计问题
使用全局变量 对于每个测试都要重置所有的全局状态(否则,不同的测试之间会相互影响) 很难理解哪些函数有什么副作用。没办法独立考虑每个函数,要考虑整个程序才能理解是不是所有的代码都能工作
对外部组件有大量依赖的代码 很难给它写出任何测试,因为要先搭起太多的脚手架。写测试会比较无趣,因此人们避免写测试。 系统会更可能因某一依赖失败而失败。对于改动来讲很难知道会产生什么样的影响。很难重构类,并且要考虑更多恢复路劲
代码又不确定的行为 测试会很古怪,而且不可靠。经常失败的测试最终会被忽略。 这种程序更可能会有条件竞争或者其他难以重现的bug。这种程序很难推理。产品中的bug很难跟踪和改正。

另一方面,如果设计的代码容易写出测试,是个好现象。如下表所示为可测性较好的代码的特征,以及它所产生的优秀设计:

特征 对可测性的好处 对设计的好处
类中只有很少或者没有内部状态 很容易写出测试,因为测试一个方法只要较少的设置,并且有较少的隐藏状态需要检查 有较少状态的类更简单,更容易理解
类/函数只做一件事 要测试它只需要较少的测试用例 较小/较简单的组件更加模块化,并且一般来讲系统有更少的耦合
每个类对别的类的依赖很少;低耦合 每个类可以独立地测试(比多个类一起测试容易的多) 系统可以并行开发。可以很容易修改或者删除类,而不会影响系统的其他部分
函数的接口简单,定义明确 有明确的行为可以测试。测试简单接口所需的工作量较少 接口更容易让程序员学习,并且重用的可能性更大

小结

《编写可读代码的艺术》这本书看完了,也总结了三篇读书笔记,分别为编写可读代码的艺术:初·代码审美编写可读代码的艺术:次·循环逻辑优化编写可读代码的艺术:末·代码块&测试。 这三篇文章中,对代码的优化的范围越来越大,难度也越来越高,从基本的变量名字修改到循环逻辑优化,再到本文中整个代码块的设计和测试代码的可读性,到这里时,已经不是寥寥数语可以记录的,知识点和理论很少,说起来也很简单,我甚至把四大部分中的后两部分合并写做一篇博客,因为讲起来真的很容易,但需要的是大量的实践和总结。原来觉得一个高级程序员或者说有经验的程序员,就是代码量很多,做过很多项目,现在才觉得,代码的设计,项目的结构,合理的测试等等,这些才是更重要的。写代码这件事情,并不是表面看起来那么的体力活,或许每个程序员都应该把自己看做一个作家,虽然这个世界上有很多种语言,我们的目的不是熟练某一种语言,也不是仅仅能够写出完整的“作品”就可以了,更重要的,是写出“艺术感”的“作品”。知识的海洋太过浩渺,世界上的聪明人数不甚数,撸起袖子加油干,共勉。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容