What is the Open-Close Principle in SOLID Principles?
Definition. Software entities (such as classes, modules, and functions) should be open for extension but closed for modification.
Key Concept of OCP
1. Open for Extension
This means that you should be able to add new features or behaviors to a software entity without changing its existing code.
You can do this by extending the entity, creating new classes, or implementing new methods or functions.
2. Closed for Modification
Once a software entity is stable and functioning correctly, you should avoid making changes to its existing code.
Modifications to existing code can introduce new bugs or break existing functionality.
The principle encourages preserving the stability of existing code.
Benefits of OCP
The OCP promotes software 1) reusability, 2) maintainability, and 3) extensibility.
It reduces the risk of introducing new defects when adding new features and helps isolate changes to specific parts of the codebase.
How to Implement OCP?
- Use of Abstraction and Interfaces: To achieve the Open/Closed Principle, developers often use abstraction (e.g., abstract classes or interfaces) to define a contract that can be implemented by different classes.
New functionality is added by creating new classes that implement these abstractions rather than modifying existing classes.
- Inheritance and Polymorphism: By using inheritance and polymorphism, you can create new classes that extend the behavior of existing classes without modifying the existing code.
End Result
Due to regression, Once stable, code should remain stable, and unnecessary modification should not be done in it.
Example Code following Open Close Principle.
- The class should be extendable.
- Modification is not allowed in class.
We want to write code that calculates the area of different shapes.
// Create instances of different shapes
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Shape triangle = new Triangle(3, 4);
// Calculate and display the areas of these shapes
Console.WriteLine("Circle Area: " + circle.Area());
Console.WriteLine("Rectangle Area: " + rectangle.Area());
Console.WriteLine("Triangle Area: " + triangle.Area());
But right now, we only want to calculate the area of a circle.
Step 1. Hence we will create an abstract shape class.
using System;
// Define an abstract base class for shapes
public abstract class Shape
{
public abstract double Area();
}
Step 2. We will write a concrete implementation of the "Shape" base class.
// Create concrete shapes by extending the base class
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public override double Area()
{
return Math.PI * Math.Pow(Radius, 2);
}
}
Step 3. After 1 month, new requirement - our code should be able to calculate the area of the Rectangle.
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override double Area()
{
return Width * Height;
}
}
Step 4. After 6 months, New requirement - our code should calculate the area of the Triangle also.
// Add a new shape (Triangle) without modifying existing code
public class Triangle : Shape
{
public double BaseLength { get; set; }
public double Height { get; set; }
public Triangle(double baseLength, double height)
{
BaseLength = baseLength;
Height = height;
}
public override double Area()
{
return 0.5 * BaseLength * Height;
}
}
In this example, we have an abstract Shape class with an abstract method Area().
Concrete shapes (Circle, Rectangle, and Triangle) are created by extending the Shape class.
Notice that we can add a new shape (Triangle) without modifying the existing code.
This demonstrates the Open/Closed Principle, as the software entities (shapes) are open for extension (we added a new shape) but closed for modification (we didn't need to change the base class or existing shapes).