Open-Closed Principle Explained
What is the Open-Closed Principle?
The open-closed principle is one of the five SOLID principles for object-oriented software development. It was first defined by Bertrand Meyer in 1988 in his book “Object-Oriented Software Construction”, where he explained it as:
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
This means that we should write code such that we can add new functionality without changing the existing code.
Why is Open-Closed Principle Important?
This principle is important because it prevents situations where a change in one of the classes requires you to adapt all depending classes, as oftentimes, modification may introduce bugs and errors into the code and lead to unexpected results in the program. This makes the program fragile, rigid, unpredictable, nonreusable, and difficult to maintain.
The open-closed principle uses interfaces or abstract classes to allow different implementations which can be easily substituted without changing the code that uses them. The interfaces are closed for modifications and new implementations can be provided to extend the functionality of the application. The main benefit is that an interface introduces an additional layer of abstraction which enables loose coupling. These interface implementations are independent of one another and do not need to share any code.
How can Open-Closed Principle be applied?
Let us look at an example of how the open-closed principle can be applied. The UML diagram below depicts the relationship between a graphic editor and the shapes it can draw.
The code implementation of the classes is shown below.
public class GraphicEditor {
public void drawShape(Shape s) {
if (s.type == 1) {
drawRectangle(s);
} else if (s.type == 2) {
drawCircle(s);
}
public void drawCircle(Circle r) {...}
public void drawRectangle(Rectangle r) {....}
}public class Shape {
int type;
}public class Rectangle extends Shape {
public Rectangle() {
super.type = 1;
}
}public class Circle extends Shape {
public Circle() {
super.type = 2;
}
}
When we want to add a new shape for the graphic editor to be able to draw, the method drawShape
in the GraphicEditor
class has to be modified. Such modification is not desirable as it is changing the existing code in order to add a new functionality. This makes the code hard to maintain as the code has to keep changing with more shapes added. More importantly, it could break the program as new changes may lead to undesirable consequences on other classes that also interact with the GraphicEditor
class.
To resolve the issue, we could introduce a layer of abstraction, which is the Shape
interface, between the GraphicEditor
class and the different shape classes that will implement this interface, as shown below.
When a new shape is added, such as an oval, there is no need to modify the code in the GraphicEditor
class. Instead, we can create a new class for the oval shape that just has to implement the Shape
interface with its own draw
method defined. The code implementation is shown below.
public class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}public interface Shape {
public void draw();
}public class Rectangle implements Shape {
public void draw() {
//draw the rectangle
}
}public class Circle implements Shape {
public void draw() {
//draw the circle
}
}public class Oval implements Shape {
public void draw() {
//draw the oval
}
}
This implementation method aligns with the open-closed principle as we no longer have to modify any existing code, but instead, we are just extending the code by adding new shape classes that implement the Shape
interface whenever new shapes are introduced for the graphic editor to draw.
Conclusion
The open-closed principle remains highly relevant and important in software engineering. By following this principle, it helps to mitigate the risks of breakages in programs when introducing new functionalities as it ensures the loose coupling of modules with the use of interfaces or abstract classes.
I hope you have gained a better understanding of the open-closed principle. Thank you for reading!