结束语 对代码的信心要从测试里来 你好,我是郑晔!

《程序员的测试课》到这里已经接近尾声了,经过整个专栏的学习,相信你对“程序员该如何做测试”这件事已经有了一个更加完整的认识。这一讲我们不去深入技术细节,我想先从一本书和你聊起。

无知之错和无能之错

这本书叫《清单革命》,作者是阿图·葛文德,他是一名医生,曾是白宫最年轻的健康政策顾问。在书的开篇作者提到,人类的错误可以分为两大类型。第一类是“无知之错”,我们犯错是因为没有掌握相关知识。第二类是“无能之错”,我们犯错并非因为没有掌握相关知识,而是因为没有正确使用这些知识。无知之错,可以原谅,无能之错,不可原谅。

在作者看来,目前这个世界上还有很多疾病没有很好的治疗方案,这个算是无知之错。但在真实世界中,很多治疗的失败却是因为医疗团队没有做好该做的事,那就属于无能之错了。

这个分类方式给了我很大的震撼,让我一下子想明白很多事。有了分类,针对不同的错误,我们可以采用不同的修正方式。无知之错,因为欠缺的是知识,所以如果要修正这类错误,需要补充相关的知识。而无能之错并非知识的欠缺,所以,要修正这类错误,需要改进的是工作的方法和流程。

身为程序员,我们是幸运的,我们生活在一个对软件有巨大需求的时代。但实事求是地说,软件也是各种问题的高发地带,我们在其中不停犯着各种错误,很多甚至是低级错误。

这些错误应该归为哪种类型的错误呢?

在外人看来,软件开发团队就应该有做好软件的能力,没做好肯定就是各种疏忽造成,这种错误是一种无能之错,要解决无能之错,显然就应该从改进工作方法和流程入手。于是,我们看到很多公司一旦觉得自己的公司需要提升软件质量了,首先是引入一套新的流程,无论是拼命写文档,还是引入专人负责。然而结果是软件团队疲于应付各种流程,软件的实际质量却并未得到有效改善。虽然初衷是好的,但因为诊断错了病因,用错了药方,治不好病也就在所难免了。

软件质量的病不在外部,而在内部。一个没有质量意识的团队只靠外部的推动很难做出高质量软件,这就像一个孩子如果仅仅靠家长的逼迫很难取得长期的好成绩一样。然而,软件质量靠流程却成了行业中的常态,不得不说,这是一个悲哀的结果。孩子想取得好成绩,归根结底是要有自己对学习的热爱,同样,软件质量要想得到真正的提升,要将做到内建质量(Build Quality In)。

内建质量

内建质量,就是将质量的思考内建于软件开发的全生命周期中

说起来很简单,然而,产品经理一拍脑袋,程序员拼命加班,把一个漏洞百出的软件送到了测试人员手里。然后,在业务强大的压力之下,测试人员闭着眼睛,把一个质量不彰的软件送上了线。每个环节都在放水,结果就是水漫金山。线上系统问题不断,新的需求接踵而来,团队疲惫不堪。然而,没有人真正地想问题到底出在哪里。这才是很多团队的真实情况。

在这样的团队中,质量只是测试人员的事,相当于把整个团队的责任压在了少数人的头上,线上出问题就是情理之中的事了。内建质量就是要把软件开发中的每一个环节都加入质量的考虑:

  • 业务负责人不能只要求上线日期,也要给出需求验证的业务目标和业务的验收标准;
  • 产品经理不只是要给出产品说明,更要给出每个需求点的验收标准;
  • 程序员不只给出代码,还要给出覆盖每行代码的自动化测试。

所谓内建质量,本质上就是用任务分解的方式,让每个环节都交付满足一定质量标准的交付物。其实,现在软件行业已经懂得了用迭代交付替代瀑布式交付,把大的需求拆分为小需求的集合,逐步交付给市场,尽早收集反馈,避免走过多的弯路。而内建质量则是通过在每个环节中加入对质量的思考,在每一个环节都要验证交付物是否符合目标,尽早发现问题。这样才不至于让测试人员成为最后的防洪堤坝,才不至于把大招憋成内伤,才有可能拿出一个高质量的软件。

在软件研发的环节加入质量的思考,对很多人来说,是一件有难度的事。因为在他们看来,这么做是增加了工作量。比如很多程序员会说“写测试就是浪费时间”。然而,真的是这样吗?

一个内建质量的团队,可以在工作的诸多环节规避掉很多问题。从软件生命周期的角度看,规避了这些问题可以从整体上节省时间。虽然很多人学过软件工程的基本理论,但这种东西实在太反直觉,就像不相信 0.99… = 1,也有很多人不相信前期的投入会给团队带来长期的回报。

但这种不相信其实更多是一种不愿意相信,因为相信了就意味着要做出改变,而改变才是很多人真正惧怕的。是的,很多人真正的不愿意是“改变”这件事。正是因为有太多的人不愿意改变,才使得愿意改变的人很容易脱颖而出。

一旦你想明白了这一点,你就能理解软件研发中暴露的很多错误根本不是无能之错,而是无知之错。换言之,正是因为很多人只愿意墨守成规,所以,他们根本看不到自己其实是欠缺了一个质量的维度,而这个维度上也有着一张知识网。

把无知之错当做无能之错去解决,根本就是走错了方向,再多的流程改进也不会让人学会写测试。因为程序员欠缺的是写测试的知识,而很少有人会意识到原来很多程序员不会写测试。解决无知之错要从知识的补充入手,而前提条件是你愿意改变。

简单的代码

感谢你一路学到这里,我相信你是愿意改变的。现在你已经具备了改变所需的基础知识,相比于还在努力改变流程的人,你已经领先了很多。对你来说,接下来要做的是花更多的时间来练习,并在练习的过程中发现自己欠缺的知识,进行相应的补充。

《程序员的测试课》虽然给了你一个写好测试的知识结构,但估计你也发现了,其实写好测试要具备的知识储备并不小,就像我在形容 TDD 所说: TDD 只是冰山一角,露在海面之上的是 TDD 的节奏,而藏在海面下的是任务分解、软件设计这些需要一定时间积累的能力。

同样,写出来的测试也是冰山一角,背后是那些需要时间积累的能力。但是,不要被这些东西吓到。其实,你在实战中已经见识过了,我写的代码很简单。有人会认为,这是一个演示的例子,所以写出来会很简单。但实际上,我在真实项目中也是这么写代码的,只不过业务逻辑更复杂一些。是的,业务逻辑复杂和代码复杂是两回事。不管业务逻辑多复杂,代码都可以写得清晰而简洁。只有那些写得不好的代码才是复杂的,会有着各种各样奇怪的写法。

优秀的代码平平无奇,糟糕的代码千奇百怪。

随着经验的丰富,我越能理解简单的价值,能坚持把代码写简单是一种能力。这需要我们不仅要有把代码写简单的意识,还要有把代码写简单的能力。好消息是,简单的代码也是容易写测试的代码,无论后续添加新功能还是修改已有的问题,难度都会下降很多,所以,它也是高质量的代码。

你只要不断地用测试作为一把尺子衡量你写的代码,你的代码质量就会越来越高。当你不知道该怎么办时,不妨回到专栏里,看看我们在专栏里是怎样解决问题的:把问题还原到简单的情形,再去想办法解决。化繁为简,是一个优秀程序员应该具备的品质。

如果整个专栏你只能记住一件事,那请记住:写代码时问问自己,这段代码应该怎么测。

在这篇结束语的末尾,我来讲个小八卦,跟你说说这个专栏是怎么来的。我在自己的公众号“郑大晔校”中写了一篇文章《为什么程序员大多不写测试?》,说的就是程序员不会写测试这件事。在文章的最后,我说程序员没有太好的方式学习写测试。《极客时间》的主编看到这篇文章就说,既然没有,那你来写一个吧。于是,有了这个专栏,也算是我自己挖坑自己填了。

这个专栏从开始构思到上线只用了一个月的时间,创下了我写作专栏的记录。算起来,这已经是我在《极客时间》写的第四个专栏了,我能够梳理成体系的结构化思考都以专栏的形式呈现了。当然,如果你还对我零散思考有兴趣,不妨关注我的公众号“郑大晔校”。

这次的《程序员的测试课》之旅就暂告一段落了!如果以后有机会,我会再来与你分享我对软件开发的理解。

最后是我们的小福利环节,我给你留了一个有奖小问卷,希望你花两分钟来填写一下,你的反馈意见对我来说很重要,我会根据你的意见持续维护这个专栏。

再见!

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/%e7%a8%8b%e5%ba%8f%e5%91%98%e7%9a%84%e6%b5%8b%e8%af%95%e8%af%be/%e7%bb%93%e6%9d%9f%e8%af%ad%20%e5%af%b9%e4%bb%a3%e7%a0%81%e7%9a%84%e4%bf%a1%e5%bf%83%e8%a6%81%e4%bb%8e%e6%b5%8b%e8%af%95%e9%87%8c%e6%9d%a5.md