Open Closed Principle (OCP)

Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.


http://deviq.com/open-closed-principle/



Open for extension: new behavior can be added to satisfy the new requirements.
Close for modification: to extending the new behavior are not required modify the existing code.


What we are basically talking about here is to design our modules, classes, and functions in a way that when a new functionality is needed, we should not modify our existing code but rather write new code that will be used by existing code.
This sounds a little bit strange, especially if we are working in languages like Java, C, C++ or C# where it applies not only to the source code itself but to the binary also.
We want to create new features in ways that will not require us to redeploy existing binaries, executables or DLLs.


A Module is Open when – A module will be said to be open if it is still available for extension. eg, it should be possible to add fields to the data structures it contains, or new elements to the set of functions it performs.
What it means – If attributes or behavior can be added to a class it can be said to be “open”.
A Module is Closed when – A module will be said to be closed if it is available for use by other modules. This assumes that the module has been given a well-defined, stable description (the interface in the sense of information hiding).
What it means – If a class is re-usable or specifically available for extending a base class then it is closed. One of the basic requirements for a class to be closed in this way is that its attributes and methods should be finalized because if they change all the classes which inherit the base class are affected.


OLD Method: -
  • We need to calculate areas of various shapes. We start with creating a class for our first shape Rectangle which has 2 attributes length & width
public class Rectangle {
public double length;
public double width;
}
  • Next, we create a class to calculate area of this Rectangle which has a method calculateRectangleArea() which takes the Rectangle as an input parameter and calculates its area –
public class AreaCalculator{
 public double calculateRectangleArea(Rectangle rectangle){
   return rectangle.length *rectangle.width;
 }
}
  • Now let's say we get our second shape circle. So we promptly create a new class Circle with a single attribute radius –
public class Circle{
public double radius;
}


  • Then we modify AreaCalculator class to add circle calculations through a new method calculateCircleArea() –


public class AreaCalculator{
 public double calculateRectangleArea(Rectangle rectangle){
   return rectangle.length *rectangle.width;
 }
 public double calculateCircleArea(Circle circle){
   return (22/7)*circle.radius*circle.radius;
 }
}


Let’s say we have a new shape pentagon next. In that case, we will again end up modifying AreaCalculator class. As the types of shapes grow this becomes messier as AreaCalculator keeps on changing and any consumers of this class will have to keep on updating their libraries which contain AreaCalculator.
As a result, AreaCalculator class will not be baselined(finalized) with surety as every time a new shape comes it will be modified. So, this design is not closed for modification.
New Design:
public interface Shape{
 public double calculateArea();
}
public class Rectangle implements Shape{
 double length;
 double width;
 public double calculateArea(){
   return length * width;
 }
}
public class Circle implements Shape{
 public double radius;
 public double calculateArea(){
   return (22/7)*radius*radius;
 }
}
public class AreaCalculator{
 public double calculateShapeArea(Shape shape){
   return shape.calculateArea();
 }
}

  • The design is open for an extension as more shapes can be added without modifying the existing code. We just need to create a new class for the new shape and implement the calculateArea() method with a formula specific to that new shape.
  • This design is also closed for modification. AreaCalculator class is complete w.r.t area calculations. It now caters to all the shapes which exist now, as well as to those that may be created later.
If we apply this principle we will get extensible systems that will be less prone to errors whenever the requirements are changed. We can use the abstraction and polymorphism to help us apply this principle.


Benefits:
  • Code maintainable and reusable.
  • Code more robust.


Buy Clean Code by Robert C Martin



Comments