关于TDD的观点:质量是反复思考的结果,仅靠解决Bug无法获得

2008 年 7 月 07 日

通过单元测试可以改善代码质量”这一观点已经得到广泛认可。培训师、顾问兼咨询师Michael Feathers 在最近的帖子中对其提出了质疑。他谈及单元测试、集成测试、TDD 和净室软件开发( Clean Room Software Development ),认为代码质量是反复思考的结果,仅靠解决 bug 无法获得。M3P 的独立咨询师 Steve Freeman 进一步阐述了 Michael 的观点,从“认知方面对TDD 进行了分析”,并解释了TDD 的好处从何而来。

Michael 认为,利用测试找 Bug 来改善质量的想法是有不足之处的

对于单元测试,最常见的理论就是“通过解决测试找到的 bug,软件的质量得以提升”。乍听起来,好象没错儿。测试有通过或失败两种结果,一旦失败,我们就知道肯定是有什么地方出了问题,就要修复它。假如你赞同这个说法,你就会预期在做集成测试时发现更少的集成错误,在做单元测试时也是一样。这个观点貌似挺好,不过它是错误的。能够证明这一点的最佳方法就是:将单元测试与另一种提高质量的方法相比较,而且这种方法有着很好的度量效果。

为了证明他的观点,Michael 提到净室软件开发(Clean Room Software Development),这是一种在上个世纪八十年代曾被使用的开发方法。根据 Michael 所述,净室方法不包括任何单元测试过程:

净室方法背后的观念,就是要通过更严格的开发纪律来提高质量;在净室中,你要为每一小短代码写逻辑断言;在代码复查时,你还要证明代码的功能和你写的断言完全符合,功能不多也不少。这种方法非常严格,甚至比我所说还要极端,因为净室方法的另一个宗旨是:不能有单元测试。一个都没有。毫无必要。代码开发完成之后,只要被复查过就被认为是完全正确的。唯一的测试就是在功能层面的随机测试。

使用净室方法的结果很有趣:不经任何单元测试,代码质量也提高了。净室方法和 TDD 方法的相似之处在于:迫使开发人员不断复查、重构并改进他的代码。Michael 的结论就是:

我认为,我们不能机械地看待测试。单元测试并不能在“单元”这个层次上通过抓到错误来改进质量。而且,集成测试也不能在“集成”这个层次上通过抓到错误来提高质量。实际上背后的道理难以言说。质量是反复思考的结果——**严谨的** 反复思考。这就是关键。强化纪律的技术一定会提高质量。

从 Michael 的帖子出发,M3P 的独立咨询师 Steve Freeman 进一步阐述了这个观点,并谈到“对 TDD 在认知上的分析”。开发人员的某些决定会影响他们的代码:

事实证明,人们并没有真正花时间从各种可行的方案中进行权衡,而是使用了“首先契合(first-fit)”的方法,即将已知的解决方案按序排列,然后选择第一个看上去最好的方案。所有这些都是在潜意识下发生的。在这之后,我们迟钝的理性思维才会想办法证明这个已成事实的决定——我们甚至都不知道这些是如何发生的。

关键在于不要直接采纳第一个在我们脑海里出现的解决方案,而是要评估不同的可选方案,这就是 Steve 认为 TDD 有益的原因:

测试驱动开发打破“首先契合”这种模式匹配,从而发挥了(或应该发挥)作用。通过 TDD,我们不再强制用脑海中出现的第一方案来解决问题。我们也不得不远离自己的“安全地带(comfort zone)”来考虑真正需要实现的需求。更重要的是,从“写一个测试开始”迫使我们首先去想真正需要的是什么(要测试什么),然后再用我们专家般敏锐的大脑来得出解决方案。

Steve 举了一个例子来证明他的观点:

最有力的证据就是 Arlo Belshee 所在的小组,他们实现了无序结对编程(Promiscuous Pairing)。他们从经验中发现:相对于成员自己决定结对时间,强制他们每隔几个小时就切换结对,这样的生产率最高。他们认为,这样可以保持每个人处于“初学者”的心态,也就可以像“初学者”那样思考。

英文原文链接: TDD Opinion: Quality Is a Function of Thought and Reflection, Not Bug Prevention

2008 年 7 月 07 日 07:56446
用户头像

发布了 100 篇内容, 共 16.7 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

第十一周学习总结

菲尼克斯

云上度假村木莲庄酒店助你远离城市的喧嚣

InfoQ_967a83c6d0d7

漫画解读:唐僧师徒如何帮助大唐官网打造CDN+OSS完美架构?

巨侠说

市值管理机器人,刷量机器人,做市机器人

WX13823153201

市值管理机器人

技术揭秘:华为云DLI背后的核心计算引擎

华为云开发者社区

大数据 spark 数据湖 华为云 DLI

Docker 之常见应用部署

哈喽沃德先生

Docker 容器 微服务 容器技术 容器化

用户密码验证函数

周冬辉

加密

安全架构和高可用系统的架构

周冬辉

高可用系统的架构

架构师 0 期第十一周命题作业

何伟敏

【华为云数据库技术大公开】机房失火后,还能拯救你的数据吗?

华为云开发者社区

数据库 机房 华为云 数据存储 云数据库

Week11总结

熊威

有了MDL锁视图,业务死锁从此一目了然

华为云开发者社区

MySQL 数据库 华为云 MDL锁视图 元数据

实用!教学白板跨国低时延互动技术实现指南

ZEGO即构

OSS 全站加速 集群

第 0 期架构师训练营第3周作业1

傅晶

组合模式

Week11作业1

熊威

数据隔离、访问授权,用好大数据为什么这么难?

华为云开发者社区

大数据 数据湖 华为云 DLI 数据隔离

一周信创舆情观察(8.10~8.23)

统小信uos

如何在3秒内打开一个网址

BabyKing

Apache Pulsar 社区周报:08-15 ~ 08-21

Apache Pulsar

云原生 Apache Pulsar 消息系统 消息中间件

90%的开发都没搞懂的CI和CD!

ci DevOps 持续集成 持续交付 持续部署

白板技术实践:在线教育平台如何保障课件数据安全

ZEGO即构

加密解密 OSS 鉴权

java安全编码指南之:拒绝Denial of Service

程序那些事

Java 安全编码指南 java安全编码 DOS攻击 zip炸弹

浅谈业务系统设计哲学

滴滴普惠出行

Newbe.Claptrap 框架入门,第四步 —— 利用 Minion,商品下单

newbe36524

云计算 微服务 dock .net core ASP.NET Core

Docker 镜像构建之 docker commit

哈喽沃德先生

Docker 容器 微服务 容器技术 容器化

CUDA,cuDNN,pytorch 在win10环境下的下载安装

Qx

教程 PyTorch

netdata安装到redhat7.6最简手册

橙子冰

netdata

第十一周命题作业

菲尼克斯

奈学:Executor线程池的概述

奈学教育

线程池 Executor

奈学:Executor线程池的概述

古月木易

线程池 Executor

前端训练营(15)-动画

罗思雨

前端进阶训练营

关于TDD的观点:质量是反复思考的结果,仅靠解决Bug无法获得-InfoQ