Inheritance 派生、组合、构造函数、接口和TDD

Inheritance 派生、组合、构造函数、接口和TDD,inheritance,interface,constructor,tdd,composition,Inheritance,Interface,Constructor,Tdd,Composition,开发TDD时,对象会随着代码的发展而“增长”。首先,它们只包含一些功能,然后添加新功能。基本上可以通过组合和/或继承来实现 同时,您几乎总是使用接口(用于测试和生产代码)来确保低耦合、依赖项反转、依赖项注入和模拟 你是如何做到这一点的 我的意思是,例如:您创建了一个类,现在它必须包含一个新属性(例如,一个人现在可以有一封电子邮件)。怎么办 修改类,添加新属性:然后必须添加新的构造函数。但若您修改现有的构造函数,那个么您必须重构所有涉及的测试,而不仅仅是生产代码。在添加新属性时,您可以尝试保留所

开发TDD时,对象会随着代码的发展而“增长”。首先,它们只包含一些功能,然后添加新功能。基本上可以通过组合和/或继承来实现

同时,您几乎总是使用接口(用于测试和生产代码)来确保低耦合、依赖项反转、依赖项注入和模拟

你是如何做到这一点的

我的意思是,例如:您创建了一个类,现在它必须包含一个新属性(例如,一个人现在可以有一封电子邮件)。怎么办

  • 修改类,添加新属性:然后必须添加新的构造函数。但若您修改现有的构造函数,那个么您必须重构所有涉及的测试,而不仅仅是生产代码。在添加新属性时,您可以尝试保留所有构造函数,但最终大部分都会变得无用、过时(仅因测试而存在),具有“构造函数调用另一个构造函数”的复杂逻辑(或使用某种“工厂”)
  • 派生类:这对OCP来说更容易编译。但是,如果你用一小步制作一个真正的TDD,如果你总是从一个非常简单的类开始派生,那么你最终会得到一个非常复杂而且不必要的继承。此外,它还假设您必须始终只测试公开曝光的成员。因此,同样,随着基类受到保护,必须重构测试以访问公共测试
  • 编写:编写构造函数没有问题,但并不总是一个好的解决方案。至于我们目前的例子
在某种程度上,接口也会发生类似的事情

因此,随着代码的增长,构造函数和接口必须不断发展。我心中有三条戒律:

  • 您应该避免重构测试
  • 生产代码不得保留“仅用于测试的代码”(即构造函数)
  • ISP声明使用特定接口。随着代码的增长,它们中的许多变得不必要,因为它们只用于测试(即模拟)在许多情况下应该被保护或私有的类

所以,正如我说的。。。在开发TDD时如何管理所有这些?我知道这是一个很长的问题,所以,如果你能参考一些好的文章或资源

改变你的测试是可以的

您所描述的(此人现在有一封电子邮件)是规格的更改。单元测试应该是您的规范,所以在引入新数据时必须更改它们是正常的

这种测试的脆弱性是一种品质的权衡,是一种必要的罪恶

不要过度工程化

通过尝试应用OCP、继承和组合来添加一个字段,您只会使事情变得更加复杂。正如您所指出的,仅仅为了测试,它会导致生产代码畸形,而且您还必须修改测试

如果要在现有行为族中添加新行为,OCP可能会很好,但这里的情况并非如此

使更改更易于管理

有一些策略可以使您的测试更能抵抗小的更改,但它们主要是在测试级别实现的,而不是在生产代码中实现的。此外,如果您经常在测试中寻找重复,例如在TDD周期的重构步骤中,那么这种机会很容易发现


其中之一是将“测试中的系统”创建封装在一个函数中,并在每个测试中调用它而不是普通的构造函数。使用默认值将其大多数参数设置为可选。这将允许您在一个位置进行更改(例如添加电子邮件字段),所有测试都将从中受益。这并不会使您免于修改测试套件,但您只需在一个地方进行修改。

谢谢您的回复!我现在正在检查所有我忘记标记为答案的帖子。抱歉耽搁了