20
Open-closed principle
Open-Closed Principle (or OCP for short) states:
Objects or entities should be open for extension but closed for modification.
The "Open for Extensions" means that we need to develop our code to add functionalities when new requirements are created, and "Closed for Modifications" means that we already developed our code, that went through testing and validations, this could should only be altered in case a bug has been found.
public class Rectangle
{
public double Height { get; set; }
public double Width { get; set; }
}
public class AreaCalculator
{
public double TotalArea(Rectangle[] rectangles)
{
double result = 0;
foreach(Rectangle rectangle in rectangles
result += rectangle.Height * rectangle.Width;
return result;
}
}
But our application recieved a new requirement for calculating the area of a circle.
public class Circle
{
public double Radius { get; set; }
}
For this to work, we also need to change the AreaCalculator
class.
public class AreaCalculator
{
public double TotalArea(object[] shapes)
{
double result = 0;
foreach(object shape in shapes)
{
if(shape is Rectangle)
{
Rectangle rectangle = (Rectangle)obj;
result += rectangle.Height * rectangle.Width;
}
if(shape is Circle)
{
Circle circle = (Circle)obj;
result += circle.Radius * circle.Radius * Math.PI;
}
}
return result;
}
}
With these modifications, we added a Circle
to our application.
But what if we need to add a Triangle
or a Square
? We would need to add more and more if
statements to our TotalArea
method.
This is where the Open-Closed Principle comes into our aid.
In this example, Rectangle
and Circle
can derive from the same abstract concept, a Shape
.
public abstract class Shape
{
public double CalculateArea();
}
Now, let's use the Shape
class in our "Shapes".
public class Rectangle: Shape
{
public double Height { get; set; }
public double Width { get; set; }
public double CalculateArea()
{
return Height * Width;
}
}
public class Circle: Shape
{
public double Radius { get; set; }
public double CalculateArea()
{
return Radius * Radius * Math.PI;
}
}
With our Shapes implementing the CalculateArea
from our Shape
class, we need to update the AreaCalculator
class.
public class AreaCalculator
{
public double TotalArea(Shape[] shapes)
{
double result = 0;
foreach(Shape shape in shapes)
{
result += shape.CalculateArea();
}
return result;
}
}
With these changes, now we're implementing the Open-Closed principle. Our application is open for extensions (creating a Triangle
class for example) but closed for modifications, only modifying if any bugs were founds.
20