10月阅读周·编写可测试的JavaScript代码:可测试的JavaScript之可测试的代码篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》、《JavaScript异步编程设计快速响应的网络应用》。
当前阅读周书籍:《编写可测试的JavaScript代码》。
可测试的代码
为何要编写可测试的代码
Douglas Crockford说过:“编写软件是人类做的最难的事情”,也就是说,软件要尽可能人性化是极其重要的。可测试的代码更加容易测试,意味着它更加容易维护,易维护则意味着它能让人(包括自己)更加容易理解,更加容易维护,从而又使得测试变得更加容易。
我们绕了一大圈,但这是一个良性循环。没有柏拉图式的完美代码,可测试性、可维护性和可理解性是互相关联的,对于这些内容是什么以及如在软件里应用它们,大家有很多的看法。然而,在可测试的、可维护的、可理解的代码上发现Bug并修复Bug则会简单得多。作为程序员,平时在自己的代码或别人的代码中查找并修复Bug,至少要花一半的时间,所以要善待自己,并让自己在这个过程里尽量轻松。
1、为什么要可测试的
测试代码,不管使用哪一种类型的测试,都是一件必须要做的事情。测试工作会由你或其他人来完成,即使是使用你的程序的最终用户。没有任何代码在第一次或后来的编写中是完美的,即便是最简单的JavaScript程序。
x=x+1;
这种程序也可能会有问题。如果X是一个字符串?或者是无穷大?以及是一个对象?程序会变得越来越复杂,我们只能期望测试最常用的路径。穷举测试是不可能的。编写容易测试的代码,或“可测试的”,至少可以让测试人员有机会完成最基本的且能永远保持先进的测试。
2、为什么要可维护的
程序员并不总是从零开始编写代码。有时候,我们的任务是调试和维护别人的代码。别人可能已经离开很久了,就像我们离开以前公司编写的代码已经很远了一样。在维护别人的代码时,别人可能也在维护我们的代码。除了让一切变得更美好外,可测试的代码也更易于维护。通常,我们对于代码变更带来的影响没有总体的了解,编写由可测试代码组成的测试可以帮助我们了解看似很小的变更所带来的影响。一旦知道代码如何工作—尤其是做修改以后会发生什么事情—我们就拥有了可维护的代码。这样的代码我们不必担忧。我们可以更容易地与团队成员分享这些代码,我们不需要重写代码也能完全理解它。程序规模越来越大,而完全了解代码知识的人在迅速减少。即便看似无关紧要的变更影响了其他功能,也会让这些人感到惊讶。
3、为什么要可理解的
高质量软件的第三个特点与其他两个特点交织在一起,就是阅读并理解代码的能力。理解一段代码的用途时,需要花多长时间?显然,能够对代码进行测试(以及为其准备测试)可以在很大程度上帮助理解代码是在做什么。但是,通过看一下方法或函数,能否不仅理解作者的意图,也能理解“如何”吗?如果不能理解自己6个月前编写的代码或者别人写的代码,那么代码就有严重的问题了。阅读一段代码后要了解,它不仅要令人满意,而且还要适当地满足工作需求。相反,如果我们写的代码自己都不再明白了,那么我们就失败了。代码是让人理解、维护和测试的。我们为别人写代码,这意味着我们的同事必须能够相对快速地理解代码。如果不理解代码,就无法进行测试或维护。在这种情况下,代码通常会被全部重写。我们可能扔掉垃圾代码,或者可能扔掉99%没有Bug的代码,但谁又能知道呢?如果没有可测试的、可维护的以及可理解的代码,那它就是垃圾。
什么是可测试的代码
所以究竟“什么”才是“可测试的”代码?“可维护的”代码看起来是什么样子?什么样的代码又是“可理解的”的代码?让我们深入挖掘一下这些问题。通过本书,我们会看到很多例子,展示这些内容是什么样子。
1、什么是可测试
可测试的代码就是容易被测试的代码。我猜大家会很惊讶!但是怎样让代码更易于测试呢?一般来说,使代码易于测试的特性,同样使代码易于维护,以及更容易理解:短小但也不太复杂的代码、完整的注释,以及松耦合。这些特性更让代码具有“可测试性”。利用可测试性特性和测试工具,可以让代码更具有可测试性。
2、什么是可维护
可维护的代码是一种可以移交给其他团队成员和同事,并便于接手和过渡的代码。具有良好测试并容易理解的可测试代码,比复杂的、不加注释的且没有测试的代码更容易维护。可维护的代码可以存在于一个完整的产品生命周期:产品从一个人转到另外一个人手里时,不需要部分或全部重写。可以修复和更改代码,而不必完全理解所有的代码,要有信心自己所做的修改不会影响别的功能,这样的代码就是可维护的代码。
3、什么是可理解的
看一段代码—不管是一个函数还是一段更小的代码,要花多长时间去理解?需要原作者一步一步解释一下吗?或者能在合理的时间内“理解”它吗?简单的、小型的且有注释的代码往往更加容易理解。通过单独运行来测试关于代码的假设,也能大大有助于理解。最重要的是代码可理解;否则,它将会被丢弃并重写。
如何编写可测试的代码
理解“为什么”和“什么”才能得知“如何”。这本书主要是关于如何编写、测试并维护可测试的、可维护的以及可理解的代码。显然,对已经具有可测试性、可维护性以及可理解性的代码进行测试和维护,可以让工作变得更简单。有了这个坚实的基础,可以让我们更富有成效,富有成效的人是快乐的,快乐的人也是富有成效的!这是一个良性循环,我喜欢良性循环。
1、如何编写可测试的代码
从头开始编写可测试的代码更容易一些(所有事情从头开始做都更加简单,不是吗?)。一些开发方法,比如TDD和BDD,可以产生可测试的代码,但也不是必然的。这是因为给代码编写测试不会自动让代码变得可测试。然而,从一开始的时候就关注测试,写出的代码比从头到尾都没有测试的代码更具可测试性。我不会要求大家在编写代码的时候使用TDD和BDD;但是,我认为从头就开始测试是一个很好的想法,我相信编写可测试的代码,有必要不断地进行测试。先编写测试或编写UI并非编写可测试代码的必要条件,但先编写单元测试(TDD)或集成测试(BDD)是编写可测试代码的一个基本概念:代码执行和测试,越早越好。在TDD和BDD之间,我要提出第三种方法:测试循环开发(test-while-driven,TWDD)。测试和代码是鸡生蛋和蛋生鸡的问题:有第一个,另外一个接着才会有—也就是说,不要一点代码都不写就编写大量的测试,也不要编写了大量的代码而一点测试都不编写。而是要编写一段代码后,就开始编写一段测试;或者编写一段测试后,就开始编写一段代码。
再说一下,这些方法并不一定能够编写出可测试的代码,我们仍然可以编写大量没用的测试。在一点一点编写代码和测试的时候,记住要考虑到大局:编写短小、最小依赖和最低复杂度的可隔离的代码块。
2、如何编写可维护的代码
可以以实现可测试代码的相同方式,来实现编写可维护的代码:编写短小简单的、可隔离的代码—短小,是因为代码行数越少,错误就越少;简单,是因为简单的代码更容易维护;可隔离的,这样在代码修改时,对其他代码的影响才会最小。在本书中,我们将探讨几种能让代码短小且可隔离的方法。
3、如何编写可理解的代码
不足为奇,要编写可理解的代码需要遵循相同的原则。代码越简单越容易理解。有测试的代码使我们能够进一步了解代码的意图和内部运作机理,注释可以提高可理解性。
编写代码类似于创作小说章节:多个小章节比几个大章节更容易理解。冗长的注释(方法前插入的注释块)和代码(选择有意义的变量名、遵循最佳实践、遵循一致的编码风格,等等)可以提高可理解性。负责维护代码的同事也不是白痴,给他们一些标示帮助他们理解代码,这样我们的代码才不会被丢弃和重写。
总结
软件始于意图。你想要做什么?这段代码要完成的是什么?为什么要编写它?这些都是你或你的同事每天都必须要问的重要问题。你将最初的意图(“什么(what)”和“为什么(why)”)转换到实际代码中,即“如何(how)”。本书主要关心的是“how”。首先弄清楚你想做什么,以及为什么要这么做,这是“如何”做工作的第一步,但实际处理“how”工作时,却发现其间关联不断。编程语言书籍可以在最底层的“how”上帮助你;而软件模式书籍可以在更高层次上帮助你。而本书则是希望在顶层能够清楚地解释“how”:如何编写可测试的代码,以及如何测试它。
但我们在了解“how”之前,理解软件开发中的“what”和“why”是非常重要的。
读完本篇可以有以下收获:
- 了解为什么要编写可测试的代码。
- 了解可测试的代码是什么。
- 了解如何编写可测试的代码。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)