Inheritance 可测试性的继承与组合

Inheritance 可测试性的继承与组合,inheritance,composition,testability,Inheritance,Composition,Testability,在设计我的对象时,我发现从可测试性的角度来看,组合是一个更好的选择。原因是,如果需要,我可以在运行单元测试时模拟组合结构的某些部分。如果我有继承层次结构,这是不可能的 我想知道其他人是否也发现这是一个喜欢作文的原因。另外,由于使用了继承,您还遇到了哪些其他可测试性陷阱?我相信,您越是开始使用设计模式进行开发,您就会越来越多地发现组合将比继承更受青睐。实际上,我相信《头先:设计模式》一书中的“重组合轻继承”是主要的设计原则之一 您能够模拟组成部分进行测试的示例可能是最好的示例之一 编辑:尽管设计模

在设计我的对象时,我发现从可测试性的角度来看,组合是一个更好的选择。原因是,如果需要,我可以在运行单元测试时模拟组合结构的某些部分。如果我有继承层次结构,这是不可能的


我想知道其他人是否也发现这是一个喜欢作文的原因。另外,由于使用了继承,您还遇到了哪些其他可测试性陷阱?

我相信,您越是开始使用设计模式进行开发,您就会越来越多地发现组合将比继承更受青睐。实际上,我相信《头先:设计模式》一书中的“重组合轻继承”是主要的设计原则之一

您能够模拟组成部分进行测试的示例可能是最好的示例之一

编辑:尽管设计模式的基本原则是支持组合而不是继承,但这并不意味着没有在需要继承的地方利用继承的设计模式。另一个基本的例子是decorator模式,在该模式中,您正在向一个抽象超类编码(尽管这是为了类型匹配,而不是为了实现“is-a”关系)。

四人帮的书基本上都是关于为什么喜欢组合而不是继承,并提供了许多方法。一些原因:

  • 类的数量增加了代码库的复杂性
  • 在许多较新的语言中,继承仅限于一个类,而您可以任意编写
  • 基类不能在运行时更改(本质上是运行时遇到的问题)
    这不是非此即彼的情况。他们不是竞争者

    继承也很容易进行单元测试。然而,它有时需要模拟具体类来测试抽象超类

    继承很容易被不当使用。有些设计看起来像“是a”的情况,但实际上不是——它们更微妙。有时候,它真的“行为就像”你需要某种组合(例如,一种策略)来将行为与其他属性分开。

    “支持对象组合而不是类继承”实际上来自GoF的书。Erich Gamma在书中描述了这个想法


    需要继承的一个重要模式是模板方法模式。这种模式被广泛使用,非常方便,因此继承将继续存在。另一种使用继承的常见模式是复合模式。我想说的一点是,不要忽视继承,但我希望从这么多常见的API中可以清楚地看到……

    我认为合成更容易测试的最大原因是(实现)继承倾向于创建更脆弱的耦合类(脆弱基类)而且更难单独测试


    继承肯定有它的用途,但我发现自己越来越喜欢组合而不是继承。

    这是基于上下文的。当类很简单且继承自简单公共类(config/logger)时,继承获胜。我是其他案例的组成大部分都是成功的

    听起来很像《头先:设计模式》中的第1章,“策略模式”,在这一章中,你被教导设计和编码接口,而不是实现。很好的一点是,它不是非此即彼。最近,我发现自己鼓吹这么多关于写作的东西,仅仅是因为“is-a”经常被误认为是“行为像”——至少在我的经验中是这样。提醒他们每个人都有自己的位置是很好的。班级的数量与此有什么关系?组合是否意味着比继承时更少的类?也许吧。decorator模式使用了继承和组合的组合,并且产生的类比只使用继承时更少。嗯……希望我知道为什么有人否决了这个。如果我知道一个特殊的原因,我可以尝试澄清或修改。事实上,“能够模拟组成部分进行测试”根本不是一个好例子。合成使之更容易的真正原因在于大多数模拟工具的技术限制。去掉这些限制,模拟继承就和模拟合成一样简单了。除此之外,我完全同意将组合优先于继承是一个好主意。模拟组合的部分不也需要在其上注入依赖项(使其成为聚合)吗?如果不是在单元测试中,我如何访问组件?我发现这是解释继承与组合在测试方面差异的唯一答案。值得投票。