AICon全球人工智能与机器学习技术大会8折倒计时最后一周,即将涨价>> 了解详情
写点什么

Bob 大叔谈测试驱动开发的适用性

2009 年 11 月 09 日

Bob Martin 之前在一篇颇有争议的博文中声称“那些认为测试驱动开发(TDD)会减缓项目进度的人都生活在石器时代”。现在,他又深入分析了测试驱动开发的现实适用性、角色和优势

他首先提出了一个重要问题:“TDD 取代架构了吗?”。回答:“不,但是…”:

以为通过在白板上编写一个个测试用例就可以产生清晰架构的想法简直就是胡闹。你做的某些决定与测试毫无关系。 当然,很多决定可以并且应该尽可能的延期。例如,数据库模式(schema)可以等待很长时间。使用 Spring、JSF、Hibernate 和 JPA 等的决定也可以延迟做出。业务规则的魅力在于它们可以并且应该独立于数据库和 GUI 模块而实现。

这是底线。你不能通过 TDD 得到一个完整的架构。TDD 可以告诉你某些架构决定,但是你无法在没有架构设计的情况下启动项目。因此某些预先的架构是必要的。其中最重要的一点是决定哪些架构元素可以延迟哪些不能。

回答完架构问题,Martin 又转向了下一个话题:“TDD 能够替代设计吗?”。他的回答:

不,你仍然需要所有的设计技能。你仍然需要了解设计原则和设计模式。你应该了解 UML。并且,你应该创建软件设计的轻量级模型。 …

事实上,TDD 是一门设计技术,但不是孤独的设计技术。所有的老设计规则和技能仍然适用。TDD 能够影响和增强它们。

针对他的有关“石器时代”的博文,Martin 探讨了“TDD 是否应该应用于每一行代码?”。答案还是否定的:

不。对于某些问题来说 TDD 是无益的。GUI 就是一个例子。 …

当然不仅仅是 GUI。摆弄(fiddling)的想法才是关键。如果你必须把代码摆弄到位,如果你必须摆弄一些方面以满足客户。如果存在一些不确定性只能通过快速的编辑——运行周期解决,那么 TDD 与其说是一种帮助,不如说是一种障碍。

管理的技巧在于认真的退耦(decoupling)。你需要确保识别出所有不需要摆弄的代码,然后把它们分成可以通过 TDD 编写的模块。确保摆弄的代码被隔离并降低到最少。

Martin 承认,事实上某些测试更适合稍后编写,他重申只有在必要时才需要这样做(当需要摆弄时)。最重要的原因在于“这种做法提高了每行代码和每个决定被测试的几率”,如果测试不首先编写,即使最训练有素的开发人员也会写出难以测试的代码。

Bob 大叔随后抛出了一个有趣的问题:“既然我们认可测试的必要性,为何会出现对测试优先的抵制?”。针对这个问题,他认为某些人不能增量的思考代码:

坦白说,我不知道(为何对测试优先的抵制如此强烈)。既然无论如何我们都要编写测试,很显然这不是一个生产力的问题。 或许某些人不希望编写测试打断工作流。是的,当你首先编写测试时,你不能编写一个完整的算法。你不得不随着一个个测试的添加来完成这个算法。可能某些人对这种方式不适应。

Martin 最后对一个常见说法给予了答复:“如果没有这么高的测试覆盖率,项目进度不是会更快吗?”首先,他承认对遗留环境(代码没有测试)采取高覆盖率的确需要长期的高投入。针对非遗留环境和遗留环境的新代码,他的答案则相反,在这种情况下,高度自动化的测试覆盖会提升你的速度。原因在于:

第一,你无需做太多调试。如果你已经测试了每一行代码你会怎么做?根据我的经验,调试时间完全不需要了。在去年 FitNesse 的紧张开发过程中,我几乎没有花时间调试。如果不得不把时间量化,那么可能是 5 小时或者更少。 第二,我绝不会无意中破坏代码。测试集会在数秒钟内发现这种意外!这让我无所畏惧。当你勇往直前时,你的步伐就会更快。

第三,我的测试都是系统如何工作的小例子。每当我忘记系统的某部分时,我就读一下测试例子。它们让我的进度很快赶了上来。

第四,我无需持续的与 bug 作斗争。即使我有几千个用户,我的 bug 列表很小。每周花在技术支持的时间不超过一小时,而且通常都是告诉用户如何从指南中找到解决办法。

请查看 Bob 的博客以获得更多细节和具体实例,同时拿出一点时间阅读一下大量的回复和注释中的箴言。

查看英文原文: Uncle Bob On The Applicability Of TDD

2009 年 11 月 09 日 10:331774
用户头像

发布了 501 篇内容, 共 219.1 次阅读, 收获喜欢 38 次。

关注

评论

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

深入浅出函数式编程:Stream流水线的实现原理

码农架构

Java 架构 微服务 Java 8

JDBC速查手册

jiangling500

Java JDBC

熬夜总结了 “HTML5画布” 的知识点(共10条)

魔王哪吒

学习 读书笔记 程序员 随笔杂谈 2月春节不断更

《我们脑中挥之不去的问题》 - 卓克科普(2)

石云升

读书笔记 科普 2月春节不断更

聊聊大公司创新的机制:饱和攻击

boshi

创新 七日更

架构师训练营 4 期 第7周

引花眠

架构师训练营 4 期

还傻傻分不清楚equals和==的区别吗?看完就明白了

codevald

Java 源码分析 string Object

我在极客时间录课的故事(三):课程录完了,服务才刚刚开始

小程序实战专栏作者李艺

我在极客时间录课的故事

Elasticsearch Mapping Overview

escray

elastic 七日更 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

杨明越:Kubernetes的下一仗可能是提升标准化程度

杨明越

第十二周课后作业

Binary

第十二周学习总结

Binary

Tomcat异常: Unable to process Jar entry [module-info.class] from Jar

小马哥

Java maven 七日更 二月春节不断更

Tomcat速查手册

jiangling500

Java tomcat

SpringMVC专栏 第1篇 - 快速入门

小马哥

Java spring Spring MVC 七日更 二月春节不断更

【STM32】串口通信---用代码与芯片对话

AXYZdong

硬件 stm32 2月春节不断更

Scrum Patterns:梳理产品待办列表(译)

Bruce Talk

敏捷开发 译文 Agile Scrum Patterns

「架构师训练营 4 期」 第七周 - 001&2

凯迪

架构师训练营 4 期

Spring框架源码:BeanFactory与Bean的生命周期

程序员架构进阶

Java spring 源码阅读 七日更 2月春节不断更

机器学习·笔记之:

Nydia

理解「分布式系统」曾经发生的事情

读字节

分布式事务 分布式系统 分布式数据储存 TiDB EJB

第十二周 数据应用一 作业 「架构师训练营 3 期」

feiyun123

ElasticSearch.01-简介

insight

elasticsearch 2月春节不断更

写一个用例(总结)第四周

mas

盘点关于程序员的那些经典案例

孙叫兽

程序员 程序人生 话题讨论 薪水 计算机原理

【LeetCode】情侣牵手Java题解

HQ数字卡

算法 LeetCode 2月春节不断更

熬夜7天,我总结了JavaScript与ES的25个重要知识点!

魔王哪吒

学习 程序员 面试 前端 2月春节不断更

Chrome浏览器多进程架构3个必会知识点

梁龙先森

前端 浏览器 面试题总结

日记 2021年2月14日(周日)

Changing Lin

2月春节不断更

Java SE最佳实践

jiangling500

Java 最佳实践 Java SE

9. Python 学习过程的第一个山坡,99%的人都倒在了山坡下

梦想橡皮擦

Python 2月春节不断更 python入门 python学习

MySQL 核心特性与优化

MySQL 核心特性与优化

Bob大叔谈测试驱动开发的适用性-InfoQ