违反了哪些 SOLID 原则?

Which SOLID Principles are violated?

简介


我正在写关于继承问题的硕士论文,并解决了一些问题 表明存在继承问题的指标。

像下面的例子:

示例


public static String getAnimalNoise(Animal animal) {
  if (animal instanceof Dog)
    return "Woof";
  if (animal instanceof Cat)
    return "Miau";
  return "";
}

如果给定的 Animal 实例是 Dog,方法 returns 字符串 "Woof",如果是 Cat,则 "Miau"。空弦是因为有些动物根本不发出声音。

因此正确的解决方案应该是在 Animal class.

中使用具有 getNoise 方法的多态性

我已经分析了继承问题的不同指标,想说如果 其中一些违反了 SOLID Principle.

我认为上面的例子违反了:

  1. 单一职责原则 (SRP)
  2. Open/closed原理(OCP)
  3. 里氏代换原则(LSP)
  4. 依赖倒置原则(DIP)

但我不确定是否对所有人都是如此。

我想:

违反原则


违反 SRP

因为条件语句完全违反了SRP,因为就像开关一样 case 语句或多个 if-else 语句被视为多个责任。

存在两种情况,所以改变方法的原因不止一种。

OCP 违规

因为如果添加新动物,则必须将新案例添加到方法中 所以该方法不能修改。

LSP 违规

每个分支根据动物子类型执行不同的动作。 我认为这违反了 LSP?! 我知道矩形和正方形以及 getArea 的示例,但是这些 我认为也适用于违规行为的示例。

DIP 违规

条件语句具有依赖性,这意味着语句依赖于细节而不是抽象,这违反了 DIP.

问题:


所以问题是,对于给定的例子,是否真的违反了给定的原则,推理是否正确?

SRP Because conditional statements at all violates the SRP, because like the switch case statement or more than one if-else statement are consider more than one responsibility. It exists two cases so there are more than one reason to change the method.

我强烈反对。 SRP 意味着要用少许盐来解释。阅读 Uncle Bob's article on it here - 他创造了这个原则。

我将引用重要的部分:

What defines a reason to change?

This principle is about people.

When you write a software module, you want to make sure that when changes are requested, those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function. You want to isolate your modules from the complexities of the organization as a whole, and design your systems such that each module is responsible (responds to) the needs of just that one business function.

[...] as you think about this principle, remember that the reasons for change are people. It is people who request changes. And you don't want to confuse those people, or yourself, by mixing together the code that many different people care about for different reasons.


OCP Because if a new animal is added a new case must be added to the method so the Method is not close for modifications.

正确。该方法采用一组特定的实现,并且在不修改的情况下将无法处理新的实现。


LSP Each branch executes different actions dependent of the animal sub type. Which i think violates the LSP ?!

它违反了 LSP,但出于不同的原因。如果我传入一只长颈鹿,我会得到一个意想不到的结果,一个空字符串。这意味着该方法对于 Animal.

的任何子类型都不正确

DIP The conditional statements take dependency that means the statements are dependent on details and not on abstractions which violates the DIP.

技术上是正确的,但这只是违反上述其他两个原则的副作用。这不是问题的核心。


请记住原则不是规则,因此在解释原则时不要太strict/literal。实用主义和理解 为什么 需要原则是关键。

我不同意您的示例代码违反了 LSP。 LSP定义如下:

Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T.

鉴于 Animal 的两个推导,即 DogCat 以及您的方法 getAnimalNoise 您没有对具体对象的某些可证明 属性 做出决定。你的方法是决定应该返回什么噪音,而不是自己返回的对象。

假设您可以设置动物的腿数。

Animal a = new Animal()
a.setLegFront(2);
a.setLegRear(2);

如果您的 Dog 像这样覆盖它:

 class Dog extends Animal
 {
   public void setFrontLegs(int legs)
   {
     this.frontLegs = legs;
     this.rearLegs = legs + 2; 
   }
   public void setRearLegs(int legs)
   {
     // do nothing here for demonstration purposes
   }
 }

如果你现在有一个工厂返回 Animal

Animal createAnimal()
{
   return new Dog();
}
Animal a = createAnimal();
a.setFrontLegs(2);
a.setRearLegs(2);

并且您调用方法 setFront/setRearLegs 您期望结果是 2 和 2 但实际上结果是完全不同的,即 2 和 4。所以这个例子与常见的 LSP 例子紧密相关与正方形和长方形。但对我来说,这是一个比你的例子更准确的违反可证明属性的例子。

更新其他原则

我同意你的看法,其他原则也被违反了,但对于 SRP,我同意@dcastro。