写点什么

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

  • 2009-11-09
  • 本文字数:1602 字

    阅读完需:约 5 分钟

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:332679
用户头像

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

关注

评论

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

【Flutter 专题】42 图解页面截屏与本地保存小尝试

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

【LeetCode】括号的最大嵌套深度Java题解

Albert

算法 LeetCode 9月日更

谈 C++17 里的 Observer 模式 - 补

hedzr

c++ 设计模式 观察者模式 Design Patterns c++17

Linux初体验:Linux操作系统

在即

9月日更

模块八作业

NewBranSTONE

架构实战营

架构实战营 - 模块 8 - 设计消息队列存储消息数据的 MySQL 表格

雪中亮

架构实战营 #架构实战营

JVM启动参数学习笔记一

风翱

9月日更 JVM启动参数

在线JSON转jsdoc工具

入门小站

工具

CyclicBarrier类在性能测试中应用

FunTester

线程 多线程 性能测试 线程安全 FunTester

什么是数据粒度

奔向架构师

数据仓库 9月日更

网络攻防学习笔记 Day140

穿过生命散发芬芳

9月日更 网站安全基础

linux之fping命令

入门小站

Linux

Zookeeper配置管理自动更新

Mike

【LeetCode】回文链表Java题解

Albert

算法 LeetCode 9月日更

k8s deployment controller源码分析

良凯尔

Kubernetes 源码分析 Kubernetes源码 #Kubernetes#

写给互联网工程师的5G书 | 2. 无线传输

俞凡

架构 5G

中秋节如何拍月亮

卢卡多多

9月日更

Scrum Patterns:昨日天气(译)

Bruce Talk

敏捷 译文 Agile Scrum Patterns

利用 Python 分析了一波月饼,我得出的结论是?

JackTian

Python 数据分析 数据可视化 中秋 月饼

Redis核心原理与实践--列表实现原理之quicklist结构

binecy

redis 数据结构 原理分析

Opus从入门到精通(四)Opus解码程序实现

轻口味

android 音视频 9月日更

写给互联网工程师的5G书 | 3. 基础架构

俞凡

架构 5G 网络

产品分析:谁是利益相关者?

石云升

产品经理 9月日更

Prometheus 2.22.0 新特性

耳东@Erdong

Prometheus 9月日更

【Vuex 源码学习】第六篇 - Vuex 的模块收集

Brave

源码 vuex 9月日更

小小感悟

Nydia

华强买瓜•程序员版

三分恶

程序员

模块八作业:设计消息队列存储消息数据的MySQL表格

Felix

autojs自动化框架简介

IT蜗壳-Tango

9月日更

【优化技术专题】「温故而知新」基于Quartz系列的任务调度框架的动态化任务实现分析

码界西柚

Java quartz 任务调度 9月日更

要养成编写有语义的HTML的习惯

Regan Yue

html 大前端 9月日更

Bob大叔谈测试驱动开发的适用性_Java_Mike Bria_InfoQ精选文章