大家好,我是阿萨。本期继续聊聊测试驱动开发。
测试驱动开发(TDD)是解决技术债务的银弹吗?TDD并不能防止技术债务。事实上,TDD技术本身可以创造出多层隐藏的技术债务,如果不及时发现,就会产生灾难性的后果。
为什么技术债务不是我们的错
软件的复杂性
什么是测试驱动开发?
测试驱动开发(TDD)是一种开发实践,旨在鼓励纪律、结构和优质代码。它分三个阶段进行,被称为 "TDD三角"。
红色--重新写一个测试,检查所需功能是否工作。最初测试失败是因为该功能并不存在。
绿色--写一个基本的功能实现,只要能让测试通过就可以了。
重构--修改你的实现,使其更好、更干净、更有效。
软件行业的许多人认为,TDD是技术债务的解决方案。
其论点如下。
严格实行TDD的组织对其所有代码进行单元测试
这确保所有的功能都是经过深思熟虑的
它还可以测试核心功能是否有松散或明显的失败。
代码中的任何漏洞,也就是技术债务,都会导致测试失败并破坏构建。
这就保证了没有技术债务
这种说法是否站得住脚?正如许多业内人士所知道的,它并不成立。
TDD周期的每个阶段,隐藏的技术债务都会积累起来。
这并不是因为TDD有什么问题。它可以发生在任何开发方法中。TDD的问题在于,它创造了一种虚假的安全感,导致团队认为他们的技术债务比实际要少。
隐性技术债务是如何在TDD中积累起来的?
让我们仔细看看TDD的三个阶段中的每一个。
红色阶段--隐藏的技术债务
在这个阶段会发生什么。开发人员编写测试,预计他们将在下一阶段建立的功能。
什么会出错:在 "红色 "阶段,开发人员不知道最终的实现会是什么样子。他们不知道在同行评审、管理评审或客户评论中可能引入的新需求。他们也无法预测当前模块与其他模块的所有可能的相互作用,特别是与尚未存在的未来模块的相互作用。
它是如何导致技术债务的。因为很多事情在前期不知道,开发人员不可能建立覆盖所有可能情况的测试。诚然,TDD创造了一个 "安全线束",可以捕捉重大错误。然而,许多质量问题可能存在于代码中,而这些问题是特定于实现的,在测试阶段没有考虑到。
绿色阶段--隐藏的技术债务
在这个阶段会发生什么。开发人员编写的代码能够满足客户的需求(至少在最低水平上),并使测试通过。
什么会出错?在TDD方法中,一个非常强烈的假设是,测试是好的和全面的。并非所有的测试都是正确的,或以一种明智的方式进行测试。一些开发人员没有很好的测试技能(虽然他们可能是优秀的开发人员),或者他们可能在测试方面很出色,但没有足够的时间来设计一个完美的测试。
它是如何导致技术债务的。如果单元测试不能完美地模拟功能,在实现中可能会遗漏一些重要的东西,而测试仍然会通过。
重构阶段性隐藏的技术债务
在这个阶段会发生什么。开发人员改进他们的实现,确保测试仍然通过,但代码在解决手头的问题时更加优雅和高效。
什么会出错?Martin Fowler在2005年他的Bliki上的一篇文章中简明扼要地指出了这一点。
我听到的最常见的搞砸TDD的方式是忽略了第三步。重构代码以保持它的清洁是这个过程的关键部分,否则你最终只会得到一个混乱的代码片段的集合。(至少这些代码会有测试,所以比起大多数设计的失败,这是一个不太痛苦的结果)。
它是如何导致技术债务的。即使在具有德国式精确性的软件开发团队中,也不存在100%的纪律性。一些开发人员,至少在某些时候,会做不到TDD的第三阶段,或者只做了一部分。为了解决问题而快速编写的代码,如果没有充分的重构,通常很难阅读、维护和扩展。
人们普遍认为,软件的复杂性,即没有重构而快速编写的代码的主要结果,代表了技术债务。
一个更健康的TDD形式:专注于最重要的东西
在这篇文章中,我们展示了技术债务是如何在TDD过程的三个阶段中悄悄出现的。通过努力,技术债务是可以避免的,但是对于大多数开发者来说,要想一直保持所有代码的清洁是很困难的。
现在需要的是一个优先级系统,以帮助团队了解产品中哪些部分的质量问题风险最高,并将他们的努力集中在那里。TDD不一定是一刀切的。你可以在产品的某些部分投入特别的精力进行测试,而对其他部分则要宽松一些。这可以节省大量的时间,并确保测试真的是正确的,在最需要的地方。