NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

James Grenning 访谈录:关于测试驱动开发及代码异味

  • 2015-08-31
  • 本文字数:4009 字

    阅读完需:约 13 分钟

OOP 2015 大会上,敏捷宣言的签署人 James Grenning ,就技术卓越和嵌入式C 的测试驱动开发做了两场报告。InfoQ 就以下几个问题采访了James Grenning:为什么开发者没能有效地或足够好地从事技术实践、为什么会认为TDD 是有趣的、单元测试的重要性、为什么程序员应具备优秀的代码嗅觉以及怎样才能更好地找出“糟糕的代码”。

InfoQ:您能否详细描述下“技术卓越”指的是什么?为什么它这么重要?

Grenning对我来说,技术卓越就是去成为一名工程师,去解决问题。在我们这个行业里,有太多的时候,人们似乎接受了代码一团糟并存在 bug。工程师们围坐在一圈,等待着构建他们庞大的代码。依赖的管理成了工程师们的噩梦,但他们接受了这一切现实。形如所处局面的受害者而不是主宰者。

当我去我的内科医生那看病的时候,他总是知道我所用药品的最新信息,或最新的疗法。他是个专业人士。他有在持续不断地学习新事物。他跟我说,当他开始执业的时候,医学知识的半衰期大约是 7 年。现在他说,事物变化如此之快以至于一年之内他就可能会被淘汰。

技术卓越意味着成为一名专业人士、学习以及持续改进。

InfoQ:在您看来,是什么原因导致大家在诸如 TDD或重构等技术实践上做的不够或不够好?

Grenning尽管 TDD 和重构的技术实践自 1999 年左右起就出现了(随着《解析极限编程》的出版),大多数软件开发领域的人却不知道那是什么。我记得当我还是一名年轻的工程师的时候,大量的时间花在我的雇主和我的家庭上面。没有很多的时间可以投入学习什么是最佳理念和技术。关于如何生产软件,市面上有很多的想法。但不是所有的都是那么有帮助的。所以,弄清楚把精力用在哪里是件困难的事情。当我还是一名在新领域的年轻工程师时,我认为我什么都知道。

随着经验的累积,我开始谦逊地意识到,并不是所有的事情我都懂。在这个博大精深的领域,有很多东西需要掌握。我们每个人学编程的方法都是独一无二的。就我而言,教授在展示了一些 C 程序的结构例子后,给我们布置了一道作业,去编写一个操作系统。自己去搞定它!最后我们每个人确实都用自己独特的方式把它编写出来了。好像没有人是被教会如何编程的。如果你认为自己已经是技术大师了,还会有什么动力去学习更多的知识呢?

我对准备来参加我的培训的人做了个调查。可以在培训准备答复里看到问题和回复。在那里可以看到编写软件和测试软件所用的技术存在很大的不同。大多数反馈结果显示,他们用的技术还是我们 70 年代在大学用的,以及行业在 80 年代 90 年代时使用的技术:打印语句、在调试器中下断点和执行单步跟踪。恭喜你,都 2015 年了,你却还处在使用产自上世纪 70 年代的调试技术的状态。试一下 1999 年的缺陷预防技术 TDD 怎么样!?

见识过 TDD 后,工程师们告诉我,他们没有时间去写测试用例代码。他们没有时间去积极主动地预防缺陷,但却有时间去应对这些缺陷。工程师们还告诉我,他们的老板不会允许他们编写单元测试用例。对我来说这就相当于,因为我要赶时间所以不用遵循医生的处方。

问题部分在于大多数开发者处于一个长的反馈回路中。例如我上报给老板的时间估期是三个月。两个半月后,我走向老板并带给他一个坏消息,我还需要一个月时间。不断如此。最终,在六个月后,交付了一部分原定功能。这只会让人觉得,工程师只在快到最后期限了才认真工作。这样对工程师的信誉有什么好的影响呢?不会有多少吧。

迭代地开展工作,将功能分解为一小块一小块,每隔几周交付一次,这对程序员的信誉和信心会很有益。通过测试用例的安全保障,可以捕获程序行为中的有害的变更。一旦程序员掌握了 TDD,这些都能轻松达成,而一开始就以 TDD 的方式进行编码所花费的时间与用 70 年代的方法所需的时间相差无几,70 年代的编程方法主张后续调试(见测试驱动开发的原理)。

InfoQ:您在演讲中提到 TDD实施起来充满乐趣。能举一些例子吗?

Grenning我还向参加我的培训的学员们提了一些问题,包括:你最喜欢软件开发的哪一点以及你最不喜欢软件开发的哪一点

我这样做是为了确保坐在房间里参加培训的是合适的人选。从学员们的答复中我发现,他们喜欢解决问题、创造新东西、从事设计以及挑战智力。一些人喜欢调试程序所带来的挑战。他们不喜欢花太长时间去找 bug,也不喜欢不现实的最后期限、需求变更、文档、其他人的烂代码。

我设法向他们展示,他们能在喜欢的部分(解决问题、创造价值)做得更多,并且少做些他们不喜欢做的事情(找 bug、没用的文档、延期)。

下面这段话是我在嵌入式 C 的测试驱动开发一书中对 TDD 的论述:

“TDD 是有趣的!它就像是一场游戏,你穿行在一个由技术抉择组成的迷宫中,意图得到一个高度健壮的软件同时避免泥潭般的漫长调试阶段。每通过一个测试用例,能收获到新的成就感,刷新了目标完成进度。自动化测试用例记录下假设条件、捕获判定结果并解放了心力让其能专注于接下来的挑战。”

InfoQ:您提到执行单元测试非常关键,它奠定了软件的基础。对此您能解释一下吗?

GrenningTDD 让代码去完成程序员认为代码应做的事情。开发出的模块包括可执行规格,即测试用例。测试用例精确记录了代码应做之事。如果代码开始违反规格了,测试用例就执行失败。代码的一大问题是很难预估那些多余的副作用。对一部分代码做了更改,却会导致似乎并不相关部分的代码出现问题。

如果只想让代码做你想要它做的,需要通过测试来让代码保持可控。我不是 Web 开发者,但我有学过相关内容,所以我也能控制并更新我的网站,用它来支撑我的培训和业务。在我从头开始创建了一个新的服务器之前,我的 Web 部署脚本运行良好。在我原来的服务器上,有一个命名错误的目录。同时发现在我的脚本上也存在几处错误的命名。用于校验目录的判定逻辑恰好反过来允许部署我的网站。部署脚本运行在错误的原因上。因为我恰好把错误给抵消了。

当我修复了部署脚本后,我还得在一些其他脚本上也修复出错的目录。很多时候系统可以工作是因为凑巧。对于一个可靠的系统而言,有着坚实基础的代码至关重要,这样的代码只做程序员认为它应做的事情。

InfoQ:为什么您认为程序员需要拥有良好的代码嗅觉呢?

Grenning那些想改进他们的工作代码的程序员需具备三项核心技能。良好的代码嗅觉、构想出改进设计的技能以及将烂代码改好的技能。

简单地说,如果你不能以一定的精确度甄别出代码结构中的问题,你怎么能修复问题?回想起我的职业生涯,代码评审通常只不过是一个观点。“我不喜欢那样,我会这样做”,完全没有任何论据支持。随便一个程序员都能说出“这份代码糟糕透了”类似的话,但这远不够好。厨房里的大厨闻一下空气的味道就能说“把土豆扔出去,它们坏掉了,去拿些新鲜的过来”。程序员需能甄别出代码的具体的不足之处,且能想出该如何改进代码。

InfoQ:程序员要怎么做才能在找“烂代码”方面变得更好?

GrenningMartin Fowler 在他的书中对此下了一个很好的定义。在我的书中,我又增加了一些条款。Bob Martin 在他的 SOLID 设计原则中就讨论模块化和耦合问题给出了具体的建议。开发者需要以代码异味以及编码原则来阐述这些。

为了能在找烂代码上做得更好,开发者需将自己置身于干净的代码中。干净的代码不需要注释来告诉别人代码在做什么。干净的代码能很容易做到在过后重回代码。干净的代码有测试用例,能用来说明预期结果。干净的代码的命名经过了深思熟虑。干净的代码使用元音。代码评审也有帮助,不过得少关注些观点,多聚焦代码特性,比如 DRY、SOLID 和避免代码存在明显的异味。结对编程是个编写更好的代码的好办法。你知道的,两个脑袋比一个脑袋强。关于这方面,有很多相当不错的资源,找找就能有。

InfoQ:通过加大实施技术实践来提升技术的卓越,需要做些什么?

Grenning我认为强调独自工作以及专业化的文化在某种程度上是错误的。如果你所能见的都只是你自己的代码,你会产生这样的观念,一切都很好并且已经没有什么新东西要学的了。在开发周期的后段进行代码评审意味着改进将变得最困难。公司应当鼓励员工更紧密地一起工作。结对编程对传播技术的卓越之处非常有益,这是个双向的过程。

如果你正在看这篇文章,很可能你已经理解了这个问题。那么请把它给你的朋友,看看能否帮忙把这样的信息传播出去。

InfoQ:您对员工该如何说服他们的主管(以及他们主管的主管)支持员工学习和持续改进有什么建议吗?

Grenning两千年初在 Object Mentor 的时候,我们成功说服自己接受了这样的观点,极限编程的技术实践真的很重要。我们想,既然我们信服了这个观点,我们要把这些告诉其他人,他们也会被说服的。好吧,进展没有这么快。我们开始对尚未被识别出或被接受的问题提出解决方案。我又再次发现工程师最重要的技能是解决问题。但解决问题也应该成为管理者和公司执行官的一项重要技能。所以我的建议是,不要强推解决方案。甄别出问题,然后为解决问题提供支持。要超越你个人的经验去寻找解决方案。

采访嘉宾简介

James Grenning,Wingman Software 的创始人,在全球范围内从事培训、教练及咨询。拥有超过 30 年包括在技术上和在管理上的软件开发经验,James 给软件开发团队以及团队管理带来了丰富的知识、技能和创造性。他的专业根植于嵌入式软件领域,同时在向该富有挑战性的领域引入敏捷开发实践上走在了前列。可阅读 James 的文章获取关于在嵌入式软件开发中应用敏捷的内容。他感兴趣的领域有软件过程改进、面向对象设计、编程、嵌入式系统、项目管理、极限编程、测试驱动开发、自动化测试以及敏捷软件开发。James 熟悉 Scrum,拥有 Scrum Master 及 Product Owner 资格证书。

查看英文原文: Q&A on Test Driven Development and Code Smells with James Grenning


感谢邵思华对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-08-31 11:062377
用户头像

发布了 30 篇内容, 共 81672 次阅读, 收获喜欢 1 次。

关注

评论

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

云栖大会开源重磅升级!PolarDB-X v2.2: 企业级和国产化适配

阿里云数据库开源

阿里云 polarDB 云栖大会 PolarDB-X 阿里云数据库

游戏链改NFT系统开发Web3技术

薇電13242772558

web3

从演进的视角理解微服务架构

苏格拉格拉

架构 微服务 微服务架构 架构演进

大咖说·我和我的伙伴们|云原生携手禾连健康助力医疗行业发展

大咖说

阿里云 微服务 云原生

Docker PHP 入门实践(二)

sunmking

php Docker 实战 11月月更

QuTrunk与Paddle结合实践--VQA算法示例

启科量子开发者官方号

Python 人工智能 ai框架 量子计算 量子编程

oracle中计算两个日期的相差天数、月数、年数等等

默默的成长

oracle 前端 11月月更

智采云火了的背后,是企业降本增效的刚需

ToB行业头条

产品网站的FAQ页面该如何编辑?

Baklib

产品 FAQ

Baklib|如何搭建在线帮助中心站点?

Baklib

Oracle 开发规范(一)

默默的成长

oracle 前端 11月月更

不愧是阿里内部Spring Boot笔记,从头到尾全是干货

小小怪下士

Java spring 程序员 阿里 springboot

一文带你详细了解JVM运行时内存

程序员小毕

Java 程序员 面试 后端 JVM

FOTSL:端到端的文本检测与识别方法的原理方法与优势

合合技术团队

人工智能 场景 端口 文本检测 文本识别

深圳中心化区块链交易所开发安全的重要性

W13902449729

区块链交易所搭建

并发编程中的锁、条件变量和信号量

C++后台开发

Go 并发编程 linux开发 C++开发

Oracle表空间设计基本原则

默默的成长

oracle 前端 11月月更

PingCAP 推出 TiDB Cloud Serverless Tier BETA 版

PingCAP

TiDB

uniapp引入 iconfont

源字节1号

微信小程序 软件开发 前端开发 后端开发

喜讯!麦聪DaaS平台荣获“2022行业信息化优秀产品”奖

雨果

数字化转型 DaaS数据即服务 麦聪软件

Docker PHP 入门实践 (三)

sunmking

php Docker thinkphp 11月月更

RocketMQ核心技术

苏格拉格拉

RocketMQ 消息队列 消息中间件 微服务框架

1年Java经验,信心满满出去面试,被问麻了...

Java永远的神

spring 程序员 后端 JVM Java 面试

LED显示屏有色差要怎么处理?

Dylan

LED显示屏 全彩LED显示屏 led显示屏厂家

Redis核心技术

苏格拉格拉

redis 架构 持久化 部署 集群

Dubbo核心技术

苏格拉格拉

分布式 微服务 dubbo RPC 集群

HTML学习笔记(一)

lxmoe

html 前端 学习笔记 11月月更

python数据分析-开篇什么是数据分析

AIWeker

Python 人工智能 数据分析 11月月更

Docker PHP 入门实践(一)

sunmking

php 实战案例 Docker 镜像 11月月更

Redis数据结构

苏格拉格拉

redis 缓存 Redis 数据结构

介绍:什么是智能合约dapp系统开发一站式服务

W13902449729

James Grenning访谈录:关于测试驱动开发及代码异味_架构_Ben Linders_InfoQ精选文章