SOLID Design Principles – Open / Closed Principle (OCP)


The Open / Closed principle states

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

Open to extension means that we should be able to add new behavior or features to a class and Closed for modification means that while making these changes we should not need to modify the binaries.

If we want to add new behavior that we should not need to change the existing classes or functions. We should just be able to add new classes and functions to achieve this. A simple example is that we do not need to rewire the motherboard to plug in a USB.


Now you might be thinking how can we achieve extension without making any modifications to a binary?

The answer lies in abstraction.  Once we start relying on abstractions then we many ways to apply the open close principle. In .NET we can achieve this abstraction through Interfaces and Abstract classes.

When we want to add new behavior, then we need to write new functions and new classes and this helps a single class in focus on one thing and we end up with small, easier to maintain classes. Also when we write new classes then none of the existing code is dependent on this new code and hence unlikely to introduce bug.

We can add seams to the applications which allows us to create the demarcation between different layers.


Approaches for achieving Open/Closed principle


We could pass some information as parameters which could help us avoid the modifications. For example we create a simple program to clean up temporary files on my computer at 9AM. Now I share this code on my blog and people start using it but soon people start asking for a simple modification of allowing the users to decide the time for the cleanup to run. Now if I would have allowed this time to be a user inputted parameter then my class and function would have not needed any modifications.


Inheritance is another way to achieve the open close behavior. In heritance we allow the child classes to change and extend the behavior without making any changes to the parent classes.


To achieve Composition we could use the Strategy pattern. The strategy pattern allows us to follow the plugin model where the class doing the work gets injected into the class that needs that behavior. In this case we have a level of abstraction between the calling code and called code. In this type of approach the Implementation class used Inheritance since that will inherit from the base for some implementation and the client class follows composition since it exposes itself for other classes to pass into itself.


Let us take the example of a class that calculates the area of a rectangle


To get the area of a rectangle we will pass the object of the Rectangle class and get the area back.

Now we would like to extend the AreaCalculator to calculate the area of a circle as well.

So we will change the AreaCalculator to something like below. So depending on the shape we can calculate the area of the shape.

However if tomorrow we want to extend the AreaCalculator class to include another shape then we will have to modify the class again.


Now let us try to implement the AreaCalculator class following the Open / Closed principle. Let’s start by creating an abstraction for shape. We will create a class named shape that exposes a method Area.

Now whenever we want to create a Shape we will inherit from this abstract class. Let us now create Rectangle and Circle classes inheriting from Shape. We will provide individual implementation of Area and also add the properties as applicable for each shape.

Since each shape has its own implementation of Area so our AreaCalculator becomes much simpler and robust.


And since the new classes bring in their own implementations we do not need to modify the existing functionality because of the new behaviors that we add.


Find the complete source code for this post at googledrive or skydrive.

Any questions comments and feedback are most welcome.