Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which SOLID Principles are violated?

INTRODUCTION


I work on my master thesis about inheritance problems and work out some indicators which show that an inheritance problem exist.

Like the following example:

EXAMPLE


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

The method returns the String "Woof" if the given Animal instance is a Dog and "Miau" if it is a Cat. The empty string because some animals make no noises at all.

So the correct solution for that should be use polymorphism with a getNoise Method in the Animal class.

I have analysed different indicators of inheritance problems and want to say if some of them violates a SOLID Principle.

I thought the example above violates the:

  1. Single responsibility principle (SRP)
  2. Open/closed principle (OCP)
  3. Liskov substitution principle (LSP)
  4. Dependency inversion principle (DIP)

But i'm not really sure whether it is true for all.

I thought:

PRINCIPLE VIOLATIONS


SRP Violation

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.

OCP Violation

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 VIOLATION

Each branch executes different actions dependent of the animal sub type. Which i think violates the LSP ?! I know the example of the rectangle and square and the getArea but these example i thought fits also to the violation.

DIP VIOLATION

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

QUESTION:


So the Question is, for the given example, are the given principles really violated and is the reasoning correct?

like image 441
Zelldon Avatar asked Jun 03 '15 09:06

Zelldon


People also ask

What SOLID principles does the following code violate?

Which SOLID principle is violated in the following code? I think that LSP (Liskov Substitution Principle) is violated because the subclass B cannot be substituted into a variable of type A .

Which principle is violated in this code interface IPostNew void CreatePost (); void ReadPost ();?

In this example, let's pretend that I first have an IPost interface with the signature of a CreatePost() method. Later on, I modify this interface by adding a new method ReadPost() , so it becomes like the IPostNew interface. This is where we violate the interface segregation principle.

What is the issue with the single responsibility principle?

A class should have only one reason to change. A common misconception about this principle is that people think it means that a class should do only one thing. This is not the case: a class can do multiple things. If not, you'd end up with classes that only have a single public method.


2 Answers

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.

I strongly disagree. The SRP is meant to be interpreted with a pinch of salt. Read Uncle Bob's article on it here - he coined this principle.

I'll quote the important bits:

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.

Correct. The method assumes a specific set of implementations, and would not be able to handle new ones without being modified.


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

It violates the LSP, but for a different reason. If i were to pass in a giraffe, I would get an unexpected result, an empty string. Which means the method is not correct for any subtype of Animal.


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

Technically true, but this is just a side-effect of violating the other two principles above. It's not really the core of the problem.


Remember that principles are not rules, so don't be too strict/literal when interpreting them. Pragmatism and understanding why a principle is needed are key.

like image 91
dcastro Avatar answered Oct 30 '22 20:10

dcastro


I disagree to the fact that your example code violates the LSP. LSP is defined as followed:

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.

Given the two derivation from Animal, namely Dog and Cat and your method getAnimalNoise you are not making decisions about some proveable property of the concrete object. Your method is deciding what noise should be returned and not the objects by there self.

So lets imagine you can set the number of legs for an animal.

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

And if your Dog overwrites this like this:

 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
   }
 }

If you now have a factory returning a Animal

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

And you call the methods setFront/setRearLegs you are expecting the results to be 2 and 2 but in fact the result is completely different, namely 2 and 4. So this example is tightly bound to the common LSP example with squares and rectangles. But for me its a more accurate example of a violation of provable properties than in you example.

Update for the other principles

I agree with you that the other principles are also violated but for SRP I agree with @dcastro.

like image 45
ckruczek Avatar answered Oct 30 '22 21:10

ckruczek