首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TDD是否使防御性编程变得多余?

TDD是否使防御性编程变得多余?
EN

Software Engineering用户
提问于 2016-09-23 20:21:45
回答 14查看 12.4K关注 0票数 107

今天我和一位同事进行了一次有趣的讨论。

我是个防御性程序员。我认为,必须始终遵守“类必须确保其对象在与类外部交互时具有有效状态”的规则。这个规则的原因是这个类不知道它的用户是谁,当它以非法的方式与它交互时,它应该可以预见地失败。在我看来,这条规则适用于所有的类。

在今天进行讨论的特定情况下,我编写了代码,验证构造函数的参数是正确的(例如,整数参数必须> 0),如果不满足先决条件,则抛出异常。另一方面,我的同事认为这样的检查是多余的,因为单元测试应该捕捉到类的任何不正确的用法。此外,他认为防御性编程验证也应该进行单元测试,因此防御性编程增加了大量工作,因此对于TDD来说不是最优的。

TDD真的可以取代防御性编程吗?因此,参数验证(我并不是指用户输入)是否没有必要?还是这两种技术相辅相成?

EN

回答 14

Software Engineering用户

回答已采纳

发布于 2016-09-23 20:37:48

那太荒谬了。TDD强制代码通过测试,并强制所有代码在其周围进行一些测试。它不能阻止您的使用者错误地调用代码,也不能神奇地阻止程序员错过测试用例。

没有任何方法可以强迫用户正确使用代码。

有一个小小的论点是,如果您完美地完成了TDD,在实现测试用例之前,您会在测试用例中捕捉到>0的检查,并解决这个问题--可能是通过添加检查。但是,如果您执行了TDD,您的需求(构造函数中的>0)将首先显示为一个失败的测试用例。这样,在添加支票之后,就可以进行测试了。

测试一些防御条件也是合理的(您添加了逻辑,为什么不想测试一些如此容易测试的东西?)我不知道你为什么不同意这个观点。

还是这两种技术相辅相成?

TDD将开发测试。实现参数验证将使它们通过。

票数 197
EN

Software Engineering用户

发布于 2016-09-23 20:39:00

防御性编程和单元测试是两种不同的捕获错误的方法,每种方法都有不同的优点。只使用一种检测错误的方法会使您的错误检测机制变得脆弱。使用这两种方法都会捕获其中一种或另一种可能遗漏的错误,即使在不是面向公共API的代码中也是如此;例如,可能有人忘记为传递到公共API的无效数据添加单元测试。在适当的地方检查一切意味着有更多的机会捕捉错误。

在信息安全方面,这被称为深度防御。多层防御确保了如果一个人失败了,还会有其他人来抓它。

你的同事有一件事是对的:你应该测试你的验证,但这不是“不必要的工作”。这与测试任何其他代码一样,您希望确保所有的使用,即使是无效的使用,都有一个预期的结果。

票数 33
EN

Software Engineering用户

发布于 2016-09-23 20:40:34

TDD绝对不能取代防御性编程。相反,您可以使用TDD来确保所有防御措施就位并按预期工作。

在TDD中,如果不首先编写测试,就不应该编写代码--虔诚地遵循红绿重构循环。这意味着,如果要添加验证,首先要编写需要此验证的测试。用负数和零调用有问题的方法,并期望它抛出异常。

此外,不要忘记“重构”的步骤。虽然TDD是测试驱动的,但这并不意味着只进行测试。您仍然应该应用适当的设计,并编写合理的代码。编写防御性代码是明智的代码,因为它使期望更加明确,而且您的代码总体上更加健壮--及早发现可能出现的错误,使它们更易于调试。

但是我们不应该用测试来定位错误吗?断言和测试是相辅相成的。一个好的测试策略将混合各种方法,以确保软件是健壮的。只有单元测试、集成测试或代码中的断言都是不能令人满意的,您需要一个良好的组合才能以可接受的努力达到对您的软件的足够的信心。

然后,对您的同事有一个很大的概念上的误解:单元测试永远不能测试您的类的使用,只是类本身按照预期的方式独立工作。您将使用集成测试来检查各个组件之间的交互是否有效,但是可能的测试用例的组合爆炸使得不可能测试所有的东西。因此,集成测试应该仅限于几个重要的情况。更详细的测试也涵盖边缘案例和错误案例,更适合于单元测试。

票数 31
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/331864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档