TDD如今风行一时,越来越多的软件公司正在转向敏捷、scrum等。我当然可以看到自动化测试的优势,但我也看到TDD与良好的面向对象设计的一些原则相矛盾。
TDD要求您在代码中插入接缝,这些接缝通过接口公开实现细节。依赖注入或协作者注入违反了信息隐藏的原则。如果您的类使用collaborator类,那么这些collaborator的构造应该在类内部,而不是通过构造函数或接口公开。
我还没有看到任何关于编写可测试代码和同时坚持封装、简单和信息隐藏原则之间的冲突的文献。这些问题有没有以任何标准的方式解决?
发布于 2011-05-07 16:58:19
您认为是实现细节的方法和类实际上是接缝,它们表示轴,沿着这些轴,您可以、变化和将组件重新组合为新的星座。
关于封装的经典想法往往过于粗粒度,因为当您隐藏大量移动部分时,也会使代码变得非常不灵活。它还倾向于违反许多SOLID原则--最突出的是Single Responsibility Principle。
大多数面向对象的设计模式往往是相当细粒度的,并且很好地符合可靠的原则,这是正确的面向对象设计是细粒度的另一个标志。
如果您的类使用collaborator类,那么这些collaborator的构造应该在类内部,而不是通过构造函数或接口公开。
这是两种不同的混合在一起的东西。我同意在大多数情况下,协作者不应该通过接口公开。但是,通过构造函数公开它们是正确的做法。Constructors are essentially implementation details of a class while the interfaces provide the real API。
如果您希望保留粗粒度的应用程序接口以实现默认功能,您仍然可以通过提供一个Facade来实现。有关更多详细信息,请参阅本文:Dependency Inject (DI) "friendly" library
发布于 2011-05-07 07:18:09
也许几乎没有文献是因为它是错误的二分法?
测试驱动程序要求您在代码中插入接缝,从而通过接口公开实现细节。
不需要,用于注入依赖项的构造函数或方法不需要是调用类使用的接口的一部分:
class Zoo {
Animal exhibit;
}
interface Animal {
void walk();
}
class Dog extends Animal {
DogFood food;
Dog(DogFood food) {
this.food = food;
}
}如果您的类使用collaborator类,那么这些collaborator的构造应该在类内部,而不是通过构造函数或接口公开。
在上面的例子中,Zoo不能访问DogFood,因为它在被喂食之后才获得Dog,并且Dog不会暴露它的食物。
发布于 2011-05-08 14:58:43
Mark Seemann的回答非常好。工业中的“单元”经常破坏Single Responsibility Principle,并由于所有内部硬连接的依赖项而使系统难以维护。TDD很好地暴露了这样的缺陷。然后可以像乐高积木一样构建单元,以形成更大的功能单元,这些功能单元实际上执行有用的业务逻辑。真的,我认为TDD可以很好地支持构建好的OO系统。
不要担心隐藏太多的东西。把private想象成“你不被允许访问”而不是“系统当前不需要访问”的意思。小心使用它-通常是在错误的时间从外部访问时搞乱对象状态的事情。
https://stackoverflow.com/questions/5917601
复制相似问题