使用jmock时,如果设置类imposteriser,则可以模拟具体类。我注意到类imposterizer在遗留包中,所以我真的不想使用它(特别是因为在我的IDE中使用重构工具提取界面非常容易)。我不喜欢具体类的实例变量。
然而,提取界面,我注意到我的代码库中出现了一种模式。很多时候接口只有一个实现具体类。我更喜欢尽可能使用接口,但拥有所有这些额外文件似乎非常冗长。此外,每次我想在课程中添加新方法时,更新界面并更新实施者都会有点繁琐。
这只是你为正确抽象付出的代价,还是有一种我没有想过的更好的方法?即使接口中唯一的东西是getters / setters,所有类都应该实现接口吗?
答案 0 :(得分:10)
如果界面只是getter和setter,这听起来更像是数据而不是行为 - 并且听起来不像我那样的东西嘲笑。我很乐意在其他类的测试中直接使用简单的生产代码。我只为提供服务的类注入依赖项。
我感觉到你的痛苦,但我个人做仍然编写界面,即使目前只有一个生产实现。我常常会在嘲笑一段时间后发现我写了一个存根或伪造的实现。伪装可以最终变得更加简单(导致更清晰的测试),除非您真的对测试调用者和服务之间的交互感兴趣。
这也意味着当有人想要查看特定依赖项提供的方法时,他们可以看到只是接口,而不涉及任何实现。
答案 1 :(得分:5)
我要点的一些一般观点:
这些要点有望帮助您制作更简单,更易测试和可维护的设计。至少在尝试跟随它们之后有一些经验。
答案 2 :(得分:3)
如果它的冗长和繁琐是不好的风格,无论理论上的优势是什么。
如果使用您的工具轻松提取界面,为什么现在就这样做?当它实际上有一些真正的目的时,为什么不这样做呢。我看到太多的代码构建了未来,而不是解决手头的问题。
当然,关于这些问题的所有争论都只是意见。没有事实可以找到。
答案 3 :(得分:3)
你提到“适当的抽象”。嗯,如果界面对多个类有意义,那是唯一合适的。特别是考虑到你从具体类中提取接口,你可能最终得到了接口中不应该存在的方法。当然,如果首先存在界面本身是有意义的。
我要指出的最后一件事是你的界面似乎并不特别稳定。您似乎暗示向接口添加方法对您来说很常见。当类的合同(即它的接口)如此易变时,我会质疑类的抽象。
总而言之,我不相信立即为所有提供接口构成了适当的抽象。相反,等待类的公共接口首先稳定,然后考虑适当的抽象(即不只是点击IDE中的"extract interface..."
按钮)从设计角度来看要好得多。另外,类可能会抽象为几个不相关的接口,而不是单个接口。
答案 4 :(得分:1)
如果您的界面主要是属性,那么所有实现类可能都是相关的,也许抽象类更适合您的需求。然后你可以避免一些样板。抽象类的主要功能仍然可以通过接口进一步抽象。
interface IRunner {
void run();
int doOtherThing();
}
abstract class Thing implements IRunner {
//this is class-specific
abstract void run();
//this is common to all 'Things'
int doOtherThing() { return 0; }
//as are these properties
public int getProp() {...}
public void setProp(int val) {...}
}
public class Goo extends Thing {
public void run() {
int i = getProp() + doOtherThing();
makeMagicGoo(i);
}
}
答案 5 :(得分:0)
如果让额外的接口冒犯你,你可以创建模拟对象(手工)作为你正在模拟的类的子类。
如果一个班级仅仅由(简单的)吸气者和制定者组成,那么嘲笑它几乎没有任何意义。只需使用真实的东西。
答案 6 :(得分:0)
有一个关键的用例,即使在你只编写一个实现的情况下,为对象生成接口也是至关重要的:你希望能够为类的实例生成JDK代理(这很有用)如果你正在做Spring AOP,例如)。可以使用像cglib这样的东西为任意事物构建代理,但它要复杂得多;相比之下,JDK代理很容易。
我也有点担心你的IDE没有尽可能地帮助你。我发现使用我的(Eclipse)我可以在接口中创建方法,如果我只是在实现中用@Override
标记它们并选择正确的自动修复选项。 (这并不是说它会选择正确的方法解释,但那是你的工作。)
答案 7 :(得分:0)
请参阅此处发布的答案,该答案将重点放在界面https://softwareengineering.stackexchange.com/a/179265/74889
的合同定义角色上答案 8 :(得分:0)
我建议这样做:
关于这个主题的几个有用的链接:
https://martinfowler.com/bliki/InterfaceImplementationPair.html
https://rrees.me/2009/01/31/programming-to-interfaces-anti-pattern/