Saturday, December 10, 2016

OCP - Open Closed Principle

OCP says -  A software module/class is open for extension and closed for modification.

"Open for extension" means we need to design our module/class in such a way that the functionalities can be added only when new requirements are generated. 
"Close for modification" means we need not alter the existing class (which have already developed and has gone through unit testing) until a bug comes.

Lets see OCP with an example, suppose we have a rectangle class with height and width and our application needs to calculate the total area of the collection of rectangles. By applying SRP, we cannot add total area calculation code inside Rectangle class, so I have created a new class call ed AreaCalculator. 

public class Rectangle {
     public double Width { get; set; }
     public double Height { get; set; }
}

public class AreaCalculator {
    double area;
    public double TotalArea(List<Rectangle> rectangles)
    {  
        foreach(var item in rectangles) {
            area+= (item.Width * item.Height);
        }
        return area;
     }
}

Lets say now we need to extend our application to support circle. Now we have an issue because the AreaCalculator just takes the list of type Rectangle, but we can change this method a bit to accommodate Circle as below:

public class Circle{
    public double Radius { get; set; }
}

public class AreaCalculator {
    double area;
    public double TotalArea(List<Object> shapes)
    {  
        foreach (var item in shapes) 
        {
           if (item is Rectangle)
           {
                var rectangle = (Rectangle) item;
                area+= (rectangle .Width * rectangle .Height);
           }
          if (item is Circle)
          {
                 var circle = (Circle) item;
                area+= (circle.Radious * cirlce.Radious * Math.PI);              
          } 
        }
        return area;
     }
}

Let's say now we need to extend our application to accommodate Tingle, Square and other shapes, we will have to add new if conditions in TotalArea method which makes class AreaCalculator as open for modification  (which violates OCP). To overcome this problem we can do the following:

public abstract class Shape {
     public abstract double Area();
}

public class Rectangle : Shape {
     public double Width { get; set; }
     public double Height { get; set; }
     public override double Area(){
           return (Width *  Height);
     }
}


public class Circle : Shape {

    public double Radius { get; set; }    
    public override double Area()
    {
           return (Radius *  Radius * Math.PI);
     }
}


public class Square : Shape {

    public double Side{ get; set; }
    public override double Area()
    {
           return (Side *  Side);
     }
}

public class AreaCalculator {

    double area;

    public double TotalArea(List<Shape> shapes)
    {  
        foreach (var item in shapes) 
        {
            area += item.Area();
        }
        return area;
     }
}

Whenever a new shape is introduced the new shape class has to derive from "Shape" abstract class and we don't need to modify AreaCalculator class. 

Now our code is following SRP as well as OCP.  Awesome! Isn't it?

No comments:

Post a Comment