Question

My previous question was just with class diagram and because of some comments I thought I try to find an example with a little piece of code for the diagram to see if principles correct understood?

enter image description here

class Rectangle {
  private int width, height;

  public void setHeight(int h) { height = h; }
  public void setWidth(int w) { width = w; }
  public int area() { return height * width; }
}

class Square extends Rectangle {
  public void setHeight(int h) { height = width = h; }
  public void setWidth(int w) { width = height = w; }
}

// A test function for rectangles
public void areaTest(Rectange rect) {
  rect.setHeight = 20;
  rect.setWidth = 10;
  int area = rect.area();

  assert area == 200;
}

I think first problem is that Liskov Substitution Principle is hurt because square extends rectangle so there is no issue saying a square is a rectangle but you cannot say a rectangle is a square which the code does, so this principle is hurt I think for this reason.

Another hurt principle I believe is Single-Responsibility Principle because in class rectangle, in order to modify the properties of a rectangle for example its area(), you would need to change the entire implementation to achieve this, for the similar reason I believe the Open/Closed Principle is hurt as well because if you want add an extension let's say a draw function to draw the objects (rectangle/square), you cannot do this correctly.

I think other principles are not hurt by this design.

Was it helpful?

Solution

There is no problem with the Single Responsibility Principle. The SRP doesn't say that the class shall do only one thing. It says that it should have only one reason to change. Some will argue that this implies that it should have only one single purpose. So for a shape, setting the dimensions and calculating a couple of shape related properties seems perfectly fine !

There is indeed a problem with the Liskow Subsittution Principle, since setting the height also changes the width. This might break the post-conditions of the setters (depending on how these post-conditions are expressed). And it breaks in any case the history constraint, that says that the properties of the Rectangle should only be changed according to the primitives of the Rectangle interface (i.e. no unexplained change).

Edit: This time, there is no issue with Interface Segregation Principle (thanks to the side effects when changing length or width). Dependency inversion is not relevant here either.

On the Open/CLosed, there's some room for discussion. The private variables should not be used by the extension, since it is an implementation detail of Rectangle and Square should not know about it. So it's not so open for extension: if the class would change the way it manages the heigth and the width, the extension would no longer work. So Square should use only the public interface. To improve the situation you could consider separating the interface of Rectangle from its implementation. But this could be an overkill in such a simple case.

Licensed under: CC-BY-SA with attribution
scroll top