【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

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

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

关注

评论

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

理解RabbitMQ中的AMQP-0-9-1模型,深入java虚拟机第三版百度网盘

Java 程序员 后端

牛批!阿里的Springboot笔记,果然值得我每天熬夜啃,全栈系统化的学习路线

Java 程序员 后端

牛掰plus!裸辞后集中Java面试,凭借一个技术套路了多个面试官

Java 程序员 后端

疫情在家刷了几个月的面试题及算法,我终于拿到了字节跳动offer

Java 程序员 后端

用10个真实案列带你掌握MySQL调优,开发人员必学

Java 程序员 后端

男默女泪!阿里技术官的Docker+K8S手册,java开发视频直播

Java 程序员 后端

男默女泪!阿里技术官的Docker+K8S手册(1),java研发工程师面试问题

Java 程序员 后端

032云原生之AIOps运维

穿过生命散发芬芳

云原生 10月月更

猴子都能懂的数据库避坑指南,还说你不会?,闭关在家37天“吃透”这份345页PDF

Java 程序员 后端

疫情期间宅在家的这段时间,突然收到(余额宝,java架构师技术进阶路线图下载

Java 程序员 后端

疫情降至,我只花了7天,经历三个步骤拿到了腾讯offer,springmvc面试题常问2020

Java 程序员 后端

百度、阿里、美团,java敏捷开发模式面试题

Java 程序员 后端

直击阿里“远程面试”现场,linux驱动开发入门与实战

Java 程序员 后端

爽,字节架构师DDD(领域驱动设计,Spring事务扩展机制

Java 程序员 后端

用时半个月,终于把2020年各大公司的Java面试题精选整理成文档了

Java 程序员 后端

牺牲速度来节省内存,Redis是觉得自己太快了吗?,mysql破解版百度网盘

Java 程序员 后端

一文了解「区块链桥」:区块链桥的工作方式及四种类型

CECBC

独家!就是看透这份“347页并发编程笔记(1),mysql使用入门教程

Java 程序员 后端

用了这么多年分页PageHelper,你确定你真的会用吗?,mysql应用教程李辉答案

Java 程序员 后端

模块二作业-微信朋友圈的高性能复杂度

无名

架构实战营 「架构实战营」

牛皮了!一篇文章直接解决关于TCP的23种疑难问题!,springboot源码深度解析视频

Java 程序员 后端

架构实战营模块2课后作业

断水风春

架构实战营

炸裂!这份阿里P8大佬手写“Java核心技能精选,java笔试面试宝典

Java 程序员 后端

独家!就是看透这份“347页并发编程笔记,java开发实战经典第二版pdf下载

Java 程序员 后端

区块链让奢侈品的分销、溯源不再是难题

CECBC

独家!Java开发专家P7岗必备的MySQL高级笔记及面试宝典,面试横竖绕不开MySQL

Java 程序员 后端

玩转Git就这么简单!这些常用命令你确定都用过吗?,java多线程编程面试题

Java 程序员 后端

理解 MyBatis 是如何在 Spring 容器中初始化的,java上传视频

Java 程序员 后端

用10个真实案列带你掌握MySQL调优(1),springboot注解原理

Java 程序员 后端

爆赞!腾讯T4大牛发布Java基础核心宝典,简直就是及时雨

Java 程序员 后端

牛P牛P!Github上堪称2021最全、最新Java面试题库到底有多香

Java 程序员 后端

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