就克里斯汀的回答为基础,据我所知,接缝一词的确源于Feathers的著作《有效地使用旧版代码》。定义在第31页上:
接缝是一个您可以更改程序行为而无需在该位置进行编辑的位置。
为了举例说明什么是接缝,什么不是接缝,请考虑以下Java代码:
public class MyClass {
private final Foo foo;
public MyClass(Foo foo) {
this.foo = foo;
}
public void doBunchOfStuff(BarFactory barFactory) {
// foo.doStuff() is a seam because I can inject a mock instance of Foo
this.foo.doStuff();
// barFactory.makeBars() is a seam because I can replace the default
// BarFactory instance with something else during testing
List<Bar> bars = barFactory.makeBars();
for(Bar bar : bars) {
// bar.cut() is also a seam because if I can mock out BarFactory, then
// I can get the mocked BarFactory to return mocked Bars.
bar.cut();
}
// MyStaticClass.staticCall() is not a seam because I cannot replace
// staticCall() with different behavior without calling a class besides
// MyStaticClass, or changing the code in MyStaticClass.
MyStaticClass.staticCall();
// This is not a seam either because I can't change the behavior of what
// happens when instanceCall() occurs with out changing this method or
// the code in instanceCall().
(new MyInstanceClass()).instanceCall();
}
}
上面示例的接缝将是接缝,除非:
- 正在注入的课程是最终的。
- 被调用的方法是最终的。
基本上,接缝有助于单元测试。我可以不写单元测试MyClass
,因为调用的MyStaticClass.staticCall()
和(new MyInstanceClass()).instanceCall()
。所有单元测试MyClass
的doBunchOfStuff()
方法将不得不测试MyStaticClass.staticCall()
并(new MyInstanceClass()).instanceCall()
和所有的依赖性是被调用。相反,通过将非最终类与非最终方法(或更好的接口)配合使用,可以通过简化模拟来注入的实例Foo
并BarFactory
通过MyClass
编写使单元测试成为可能。