TDD只是大部分人的美好幻想

前言

在软件开发领域,TDD(测试驱动开发)一直以来都是一个备受争议的话题。有些人将其视为一种敏捷开发方法的基石,认为它能够提高代码质量、加速开发进程,并降低维护成本。然而,也有一些人对TDD持怀疑态度,认为它过于僵化、不切实际,甚至认为它已经过时。

Kent Beck、Martin Fowler、David关于 Is TDD Dead 这个标题引发了人们对于TDD的思考:TDD到底是一种什么样的开发方法?它的优势和局限性是什么?它是否真的适用于所有的项目和团队?本文将深入探讨TDD的现状和未来,以及它在软件开发中的真正意义。本篇文章仅适合对TDD概念有一定了解,且实战过一段时间的读者。

TDD优缺点

这里我总结下TDD的优缺点

优点:

  1. 相对完善的设计: 因为在编写具体代码前全局性思考,编写完善的测试用例,通过测试用例反推验证方案是否可靠
  2. 提早暴露问题: TDD 能够帮助开发者在编写代码之前就发现和修复潜在的 bug,因此可以减少代码中的错误。通过频繁地运行测试用例,可以及时发现并解决问题,避免 bug 的积累。
  3. 提高代码质量: TDD 鼓励开发者在编写代码之前编写测试用例,这样可以更好地考虑代码的设计和实现。通过编写测试用例,开发者可以更早地发现和纠正潜在的问题,从而提高代码质量。
  4. 提高开发者信心: TDD 能够帮助开发者更加自信地进行代码修改和重构,因为他们可以通过运行测试用例来验证代码的正确性。这种自信可以使开发者更加愿意进行代码重构和改进,从而提高代码质量和可维护性

缺点:

  1. 增加开发时间: 编写测试用例需要额外的时间和精力,有时编写单元测试的耗时跟编写实现代码时间55开,甚至可能更大。
  2. 大部分情况下TDD带来的收益是有延时性
  3. 团队适应性差: 采用 TDD 需要团队成员有较高的测试编写能力和质量意识,以及对 TDD 开发流程的认可和理解。如果团队成员缺乏相关经验或者对 TDD 持负面态度,那么很可能会导致 TDD 实施效果不佳。

优点大家应该都很熟悉了,这里我们先看缺点。

增加开发时间

如果你第一次编写单元测试 ,那么你在单元测试 编写的耗时很大概率是超过编写具体实现的代码的时间。这有部分原因来自测试相关的API的不熟悉。通过一段时间的练习,编写单元测试 耗时将会减少很多。但是这并不能保证你把编写单元测试 的耗时比编写具体实现代码的时间少。写过一段时间单元测试的人,特别是以TDD 为模式编写过的人,应该都清楚编写单元测试耗时比具体实现代码高,甚至耗时是其后者的两倍都是常有的事。

如果你在这样一个快速交付、快速迭代的团队中,单元测试 的耗时可能会成为一个挑战。在这样的团队中,时间是宝贵的资源,开发者更倾向于快速地编写和交付功能代码,而不是花费时间编写测试用例。尤其是在团队中已有测试人员的情况下,在项目初期,TDD 提早暴露问题的优势可能并不十分明显。这是因为在需求提交测试之前,团队仍需进行其他测试流程,这些流程已经能够发现大部分常见问题。因此,TDD可能只对那些不易于发现的问题具有优势,例如一些边界情况或复杂逻辑中的潜在问题。

试想下,别人的需求都写了70%,而你还在编写测试用例。当项目经理咨询你进度时,你要如何作答。然后你应用了TDD你的收益又有多少呢?

所以假设你在这种团队中,那么我建议只在一些复杂的需求中,该需求中的边界场景难以复现时采用TDD。

挑战与限制:测试驱动开发(TDD)在处理未知需求时的缺陷

有的人坚持TDD,认为一切需求都要TDD来写,认为TDD就一定要先写单元测试,后写测试没啥意义,认为后写测试时,问题基本都暴露完了。这种思维非常刻板,也会增加自己的内耗。这种观点存在一个误区,即忽视了后期测试的价值和意义。

假设你接手一个自己非常不熟悉的需求时,采用测试驱动开发(TDD)的开发流程会面临一些挑战。因为在这种情况下,我们可能缺乏对需求的深入理解,难以在一开始就设计出完善的模型。这样一来,开发过程中可能会频繁地出现大面积的变化,导致单元测试需要不断地调整甚至重构。

试想下当你TDD到70%的时候,写下一个单元测试,发现之前的方案不太合理需要重构,那大部分单元测试都白写了,你是怎样的心情。

一般情况下,针对这种不熟悉的需求,我们可能会采取另一种策略:首先全面思考设计方案是否能够满足当前需求,然后快速实现,验证方案的可行性。这种方法有助于避免在开发过程中频繁地更改方案,从而减少因需求变化而带来的调整成本。所以在这种场景下,后写测试是不错选择,虽然后写测试的价值不如先写测试,但它仍有价值。

因此,即使采用 TDD 的方式,我们也需要保持灵活性,不断地根据实际情况调整和改进我们的设计和实现。

大部分情况下TDD带来的收益是有延时性

很多情况下通过编写TDD 代码提早修复的bug,你即使不通过TDD 模式编写也会发现。例如需要将时间戳格式化成yyyy.MM.dd的时间格式化的代码,你跑上真机也能快速验证代码是否正确,更别说大部分开发团队都有个测试人员的情况下了,而这时TDD 收益也就相对不多了,这时TDD 还有个可回归性测试的收益。

但是这个收益一般只有在这块地方需要新增功能,或者其他变更的时候,可回归性测试 才充分体现。首先你要为新增的功能编写单元测试,这时写完后,这时验证我这次调整是否破坏了原有功能的时候,我只用运行下测试,就知道答案了。而如果我后期不再负责这块,而去负责了其他模块,而那个模块没有单元测试,那你编写单元测试的大部分收益则由其他人享受了。这个想法有点狭隘,但是假设你所在的团队都不写单元测试的情况下,那你很少能享受到TDD可回归性测试的收益。

所以只有团队内越来越多的人积极采用TDD 并且重视编写单元测试,才能够真正实现TDD的收益最大化。尽管有些的时候TDD带来的收益可能有一定的延时性,但长远来看,它对于项目的成功和团队的效率提升具有重要意义。

而如果在一个大家都不写单元测试的情况下,那么建议根据接手的需求的复杂度和TDD 的优缺点权衡考虑是否要TDD ,如果你接手的需求很复杂,那还是非常建议TDD的。

团队适应性差

TDD 对开发人员的代码设计能力要求比较高,因为它要求开发者在编写代码之前就要考虑代码的结构和设计,以便编写可测试的代码。这需要开发者具备良好的代码设计能力,包括对软件架构、设计模式和代码规范的理解和应用能力。此外,TDD还要求开发者具备良好的单元测试编写能力,能够编写高质量、有效的测试用例来覆盖代码的各种情况和边界条件。

此外单元测试相关的中文资料非常少,特别是TDD 实战中遇到的问题经常需要用到stackoverflow,对于想要实践TDD的团队来说,团队成员可能需要具备一定的英文阅读能力,以便学习和理解国外的相关资料和资源。此外,团队内部可能需要进行针对性的培训和知识分享,以提升团队整体的单元测试编写能力和实践水平。

还有就是TDD 这种测试驱动开发的开发流程并不是每个人都喜欢或适应。有些开发者可能更倾向于传统的开发方式,即先编写功能代码,再编写测试用例进行验证。TDD 要求在编写实际代码之前就要编写测试用例,这种开发模式提供的正反馈太慢,这可能会让一些开发者感到不习惯或不舒服。有些开发者甚至可能会在编写测试用例时产生负面情绪,这可能会成为在团队中推广TDD的阻碍因素之一。

总结

正如最早提出TDD编程原则的Kent Beck所说

Kent Beck: TDD is a question of trade-offs

TDD不是银弹,它是一个权衡问题,你想要TDD这些优点的同时就得接受这些缺点。而想要达到TDD这些优点并不只有TDD才能达到。根据实际需要,合理选择是否TDD,即使采用 TDD 的方式,我们也需要保持灵活性,不断地根据实际情况调整和改进我们的设计和实现,避免陷入盲目追求TDD而忽视实际需求的误区。

相关推荐
苏三的开发日记10 分钟前
windows系统搭建kafka环境
后端
千里马学框架16 分钟前
重学SurfaceFlinger之Layer显示区域bounds计算剖析
android·智能手机·sf·安卓framework开发·layer·surfaceflinger·车载开发
爬山算法21 分钟前
Netty(19)Netty的性能优化手段有哪些?
java·后端
Tony Bai21 分钟前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
想用offer打牌35 分钟前
虚拟内存与寻址方式解析(面试版)
java·后端·面试·系统架构
無量38 分钟前
AQS抽象队列同步器原理与应用
后端
nono牛1 小时前
安卓休眠与唤醒流程
android
9号达人1 小时前
支付成功订单却没了?MyBatis连接池的坑我踩了
java·后端·面试
用户497357337981 小时前
【轻松掌握通信协议】C#的通信过程与协议实操 | 2024全新
后端
草莓熊Lotso1 小时前
C++11 核心精髓:类新功能、lambda与包装器实战
开发语言·c++·人工智能·经验分享·后端·nginx·asp.net