Class 基于开闭原理处理继承层次结构

Class 基于开闭原理处理继承层次结构,class,inheritance,solid-principles,open-closed-principle,Class,Inheritance,Solid Principles,Open Closed Principle,当我尝试遵循这些规则时,在实现了大量用例之后,我总是以继承类的层次结构结束。通常情况下,MVVM结构中的视图模型会发生这种情况,因为它们正在发生很多变化。例如(C#,但可以是任何其他面向类的语言): 问题是,当涉及到4级或更多级别的继承深度时,它变得非常混乱,难以阅读。我还经常遇到命名问题,这是错误组合的信号(比如MainWindowViewModel、MainWindowViewModelCloseCommand、MainWindowViewModelUserRelatedProperties

当我尝试遵循这些规则时,在实现了大量用例之后,我总是以继承类的层次结构结束。通常情况下,MVVM结构中的视图模型会发生这种情况,因为它们正在发生很多变化。例如(C#,但可以是任何其他面向类的语言):

问题是,当涉及到4级或更多级别的继承深度时,它变得非常混乱,难以阅读。我还经常遇到命名问题,这是错误组合的信号(比如MainWindowViewModel、MainWindowViewModelCloseCommand、MainWindowViewModelUserRelatedProperties等等)

由于仅使用最后一个派生类(上面例子中的MyAveSoMeVeWeMealth.BunCheNeXialStices),有时我考虑将发布之前的所有继承或其他重要里程碑压缩为1类,例如:

internal class MyAwesomeViewModel
{
    public int IntProperty { get; }
    public bool BoolProperty { get; }
    public double DoubleProperty { get; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public ICommand Command1 { get; }
    public ICommand Command2;

    public MyAwesomeViewModelWithBunchNewProperties(IDependency1 dependency1, IDependency2 dependency2)
    {
        _dependency1 = dependency1;
        _dependency2 = dependency2;
        Command1 = new DelegateCommand(...);
        Command2 = new DelegateCommand(...);
    }
}
但它可能违反单一责任原则(SRP),并导致非常大的超类


问题:如何处理大量的继承问题?或者,这根本不是问题,采用这种类型的类结构也没关系?

为了让OCP为您工作,您应该确定您的客户需要的行为。这些知识可用于构建一个或多个ViewModel类随后实现的接口。为了避免继承层次结构,您可以选择组合方式来构建视图模型,具体原则是帮助您提出更好解决方案的想法/指导原则。遵循这些原则没有任何内在的好处

此处发布的继承策略不起作用。它一事无成,造成混乱和更多的工作。这不是一个好办法

但它可能违反单一责任原则(SRP),并导致非常大的超类

SRP对于什么是“单一责任”非常模糊。您可以根据需要将其定义为窄或宽。同样,原则只是指导你,让你考虑不要不必要地混合应该分开的东西

在这里,您可以说“这个类的职责是成为数据绑定视图的模型。”

超类


同样的。这只是一个指导方针。你不能说“一个类最多只能有N个成员”。此建议对于任何N都是错误的,因为N是上下文敏感的。

组合优于继承

很多时候,开发人员只关注SOLID这样的原则,而忽略了基本的组合而不是继承原则

首先要记住的是继承将您紧密地绑定到基类。这导致了诸如拒绝遗赠(违反利斯科夫替代原则)等问题

当我们在OOP中提到类时,我们定义与数据相关的行为,而不是对象。当我们根据问题试图实现的行为对问题进行建模时,我们可以得到小的构建块

您可以从MyAwesomeViewModel将核心行为定义为小类,您可以在其他类中引用它。通过这种方式,您可以轻松地使用bunchnewproperty组合对象,如myawesomeviewmodel

关于单一责任原则,这是一个非常被误解的原则SRP指出,生活在一起的行为应该一起改变。这意味着一组相互依赖且将一起改变的行为属于同一类


对于您的特定场景,视图模型通常可能不会从组合或继承中受益。视图模型是数据传输对象(DTO),它们不捕获行为。这里的代码重复很容易被忽略\可以接受。如果代码重复在您的视图模型中造成问题,只需从其他DTO中组合它们即可

在核心领域中的关键部分坚持使用。您真的需要ViewModel中的顶级OO代码,或者任何与视图相关的东西吗?有人可以争辩,但我不能肯定。我对核心领域进行了非常彻底的单元测试,但没有对视图模型进行测试。我用E2E测试介绍了这一点。但我总是坚持一些原则,比如DIP和SRP。请记住接受一个对你帮助最大的答案:)。如果您需要任何帮助,我也可以进一步澄清。
internal class MyAwesomeViewModel
{
    public int IntProperty { get; }
    public bool BoolProperty { get; }
    public double DoubleProperty { get; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public ICommand Command1 { get; }
    public ICommand Command2;

    public MyAwesomeViewModelWithBunchNewProperties(IDependency1 dependency1, IDependency2 dependency2)
    {
        _dependency1 = dependency1;
        _dependency2 = dependency2;
        Command1 = new DelegateCommand(...);
        Command2 = new DelegateCommand(...);
    }
}