🚀

#24 SOLID - Open Closed principle

2024/08/07に公開

Introduction

Last time we had a brief introduction to SOLID principles and the Single Responsibility principle. So in this post, we will talk about the 'O' - Open-closed principle in SOLID.

In previous post we created some Shape, Calculator and Printer class. These classes will also be used here. To revise the code, go here.

Open-closed principle

Software entities should be open for extension, but close for modification.

Let's have a look on LengthCalculator.

        class LengthCalculator {
            private Square[] squares;
            private Circle[] circles;
            public LengthCalculator(Square[] squares, Circle[] circles) {
                    this.squares = squares;
                    this.circles = circles;
            }
            
            public int sum() {
                    int length = 0;
                    for(int s : squares) {
                            length += 4*s.length;
                    }
                    for(int c : circles) {
                            length += 2*Math.PI*c.radius;
                    }
                    system.out.println(length);
            }
    }

There are many different kind of shapes that exist other than square and circle. If we want the calculator to handle rectangular or triangle, LengthCalculator have to be modify in this approach.

Why it is bad? Think about if you have to handle a large scale project which using this approach. Every related classes have to be changed if the request is to add new feature, which means you have to spending a lot of time on learning the whole project and sometime you may forgot to update some of the classes. It increase the chance that other developers may cause mistakes while maintain the code.

To avoid this, we can create a parent interface of shapes and contain a sum function to calculate their length.

    public interface Shape {
            public int sum();
    }

And both Circle and Square class inherit Shape.

    class Square implements Shape {
            public int length;
            public Square(int length) {
                    this.length = length;
            }
                public int sum() {
                        return 4*s.length;
                }
    }
    class Circle implements Shape {
            public int radius;
            public Circle(int radius) {
                    this.radius = radius;
            }
            public int sum() {
                    return 2*Math.PI*c.radius;
            }
    }

The current changes seperate the sum of shape logic from calculator and makes it only focus on calculate the sum of all shapes.

        class LengthCalculator {
            private Shape[] shapes;
            public LengthCalculator(Shape[] shapes) {
                    this.shapes = shapes;
            }
            
                public int sum() {
                    int length = 0;
                    for(int shape : shapes) {
                            length += shape.sum();
                    }
                    return length;
            }
    }

Now, it looks more clean, easy to update and satisfies the Open-closed principle.

References

Discussion