首先,我是 Eiffel 的软件工程师,所以我可以从经验中谈谈这件事。
TDD vs DbC的前提是不正确的
这两种技术并不矛盾,而是相辅相成。补语与断言和目的的放置有关。
TDD 的目的既有组件又有范围。TDD 的基本组件是布尔断言和对象特征(例如方法)执行。步骤很简单:
- 创建一个对象。
- 在功能中执行一些代码。
- 对对象上的数据状态进行断言。
断言失败,测试失败。通过所有断言是目标。
与 TDD 一样,Design-by-Contract 的合同具有目的、范围和组件。虽然 TDD 仅限于单元测试时间,但合同可以贯穿整个 SDLC(软件开发生命周期)!在 TDD 范围内,对象方法(特性)的执行将执行合同。在 Eiffel Studio 自动测试 (TDD) 设置中,创建一个对象,进行调用(就像其他语言中的 TDD 一样),但这里是相似的地方。
在具有自动测试功能的 Eiffel Studio 和具有合同的 Eiffel 代码中,目的有所改变。我们要测试客户-供应商关系。我们的 TDD 代码在其对象上伪装成我们的 Supplier 方法的客户。我们创建对象并基于此目的调用方法,而不仅仅是简单的“TDD-ish 方法测试”。因为对我们的方法(功能)的调用有契约,这些契约将作为我们在自动测试中的 TDD 式代码的一部分执行。因为这是真的,所以我们在代码中放置的合约断言(测试)不必出现在我们的 TDD 测试代码中。我们(作为程序员)的工作是简单地确保:A)代码+合约沿所有 N 路径执行,以及 B)代码+合约使用所有合理的数据类型和范围执行。
关于 TDD-DbC 互补关系可能还有更多要写的,但我不会在这件事上对你粗鲁。可以说 TDD 和 DbC 与其他没有矛盾——绝对不是!
DbC 合约的力量超出了 TDD 所能达到的范围
现在,我们可以将注意力转向按合同设计的合同的力量,超越 TDD 的能力!
合约存在于代码中。它们不是外部的,而是内部的。关于合约最强大的一点(超出他们的客户-供应商合约关系基础)是编译器旨在了解它们!它们不是埃菲尔铁塔的附加物!因此,它们参与了继承的各个方面(传统的垂直 is-a 继承和横向或水平泛型)。此外,它们到达了 TDD 无法到达的地方——方法(特征)内部。
虽然 TDD 可以轻松地模拟前置条件和后置条件,但 TDD 无法进入代码内部并执行循环不变合约,也无法在代码块执行时定期抽查“检查”合约。这是一个强大的逻辑和定性范式,也是按合同设计如何运作的现实。
此外,TDD 不能做类不变量,只能以最微弱的方式。我已经尽我最大的努力让我的自动测试代码(实际上只是应用 TDD 的 Eiffel Studios 版本)来进行类不变模仿。这不可能。要了解为什么您必须了解 Eiffel 类不变量如何工作的来龙去脉。因此,目前,您只需要相信(或不相信)TDD 无法完成这项任务,而 DbC 可以如此轻松、良好、优雅地处理!
DbC 的影响并不止于上述概念
我们在上面提到,TDD 存在于单元测试时。契约,因为它们在编译器的监督和控制下应用在代码中,所以适用于代码可以执行的任何地方:
工作台:作为程序员,您正在使用代码来查看它的工作情况(例如,在 TDD 时间之前或与 TDD 时间结合使用)。
单元测试:您的持续集成测试、单元测试、TDD 等。
Alpha 测试:您的初始测试用户在运行可执行文件时会被合约绊倒
Beta 测试:更广泛的用户受众也将被合同绊倒。
生产:最终的可执行文件(或生产系统)可以通过合同进行持续测试(TDD 不能)。
在上述每种情况下,您都会发现自己可以控制运行哪些合约以及从哪些来源!您可以选择性地、细粒度地打开和关闭各种形式的合约,并以极高的精度控制编译器在何时何地应用它们!
如果这一切还不够,合约(通过设计)可以做一些 TDD 断言永远无法做到的事情:告诉您调用堆栈中的哪个位置以及哪个客户端-供应商关系被破坏,以及为什么(这也立即表明如何要解决这个问题)。为什么这是真的?
TDD 断言旨在告诉您事后代码运行(执行)的结果。TDD 断言只能看到被检查方法的当前状态。TDD 断言不能从它们在代码库外部的位置做的是准确地告诉您哪个调用失败以及为什么!您会看到——您对某个方法的初始 TDD 调用将触发该方法。很多时候,那个方法会调用另一个,另一个,另一个——有时,随着调用堆栈的来回摆动,会出现中断:数据写入错误,根本不写入,或者写入它不应该的时候。
TDD就像谋杀已经发生后出现在犯罪现场的警察。他们只剩下法医线索,他们希望这些线索能将他们引向嫌疑人并定罪。但是,如果我们可以在犯罪发生时在那里呢?这就是放置 TDD 断言和合同断言之间的区别。合同是用来捕捉正在进行的犯罪的,它们直接指向犯罪者,因为它正在犯罪!
回顾
让我们回顾一下。
在一天结束时:我想要两个!在阅读完所有这些之后(如果你幸存下来),我希望你也能这样做。