TDD 与防御性编程

off*_*ine 5 tdd defensive-programming

鲍勃叔叔说:

\n\n

“非公开 API 中的防御性编程是不进行 TDD 的团队的一种气味和症状。”

\n\n

我想知道 TDD 如何避免以意想不到的方式使用(内部)函数?我认为 TDD 可以\xc2\xb4t 避免它。它仅表明该函数使用正确,因为调用函数被通过单元测试的 it\xc2\xb4s 覆盖。

\n\n

当使用(非防御性)功能开发新功能时,该功能也是使用 TDD 开发的。因此,无意使用该功能将导致新功能测试失败。

\n\n

因此,使用 TDD 来驱动新功能将迫使您正确使用(内部)功能。

\n\n

你认为这就是鲍勃叔叔\xc2\xb4s 推文的含义吗?

\n

Gho*_*ica 3

因此,使用 TDD 来驱动新功能将迫使您正确使用(内部)功能。

确切地。但请记住这里微妙的“差距”:您应该使用 TDD 编写(单元)测试来测试公共方法的契约。您不关心这些方法的实现 - 这就是所有内部实现细节。

因此:如果您的“新”代码以非预期的方式使用现有方法,您就会被“告知”,因为抛出了异常或者您收到了意外结果。

这就是我所说的“差距”:你看,上面描述了一种黑盒测试方法。您有一个公共方法 X,并且您验证了它的公共契约。与白盒测试相比,您编写测试来覆盖 X 中采用的所有路径。这样做时,您可能会注意到:“可以在我的内部方法中测试一个条件,我必须驱动这个特殊数据”。

但正如所说 - 我认为你应该进行黑盒测试-在重构内部方法时,白盒测试可能很容易被破坏。

这里还有一个额外的维度:请记住,理想情况下您会更改代码以实现新功能。这意味着添加新功能只能通过编写新的类和方法来实现。这意味着您的代码没有机会使用私有内部方法。因为你在一个班级。换句话说:当你经常碰巧遇到以多种不同方式使用你的内部方法的情况时 - 那么你可能做错了什么

理想的路径是:通过创建一组新类来实现新需求。稍后,您必须添加其他要求 - 通过编写更多类。

在这条理想路径中——内部方法中不需要防御性编程因为您完全了解此类内部方法的每个用例!

因此,结论是:避免在内部方法中进行防御性编程。确保您的公共 API 检查所有先决条件,以便在出现问题时它们会失败(尽可能快)。尽量避免这些内部一致性检查 - 因为它们往往会使你的代码变得臃肿 - 并且放心:在 5 周或 5 个月内,你将不记得你是否真的需要该检查,或者它是否只是“防御性”。