Open Closed

Open/Closed Principal (OCP) is one of the most important principal. As per Robert. C. Martin

"Open for extension": This means behavior of module can be extended. As the requirement change, we are able to extend the module with new behaviors that satisfy those changes.

"Closed for modification" : This means when we are adding/extending behavior of a module then it should not result in changes to the source or binary code of the module. The binary executable version of the module, whether in a linkable library, a DLL or a Java.jar remains untouched.

Bertrand Meyer wrote in 1988 and defined OCP like this:

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

Basically its the same, It tells you to write your code so that you will be able to add new functionality without changing the existing code.

Think about that very carefully. If the behaviors of all the modules in your system could be extended, without modifying them, then you could add new features to that system without modifying any old code. The features would be added solely by writing new code. If you do not modify any existing code then risk factor of breaking existing functionalities is drastically reduced, you need to test less, writing new unit tests to test new behavior would be clear.

Now lets see how do we achieve this -

If classes need to honor OCP then there should be defined extension points where the functionalities can be hooked into existing code. Now let's see what these extension points are? but first lets see a situation where there are no extension points defined in your code and we are asked to extend the class without modifying original module/class code.

Let's take this example. A client is getting new instance of Credit Card and performing operations to get outstanding balance, payment due date and calculating reward points.

Now let's say credit card company want to introduce new Preferred credit card product where in customers get double reward points than a regular credit card holder and also gets cash backs on most of the transactions. To address this requirement, a developer will mostly violate rule of OCP and update code in CreditCard class with "If" "else" conditions to adopt business rules. So we you to accommodate this new requirement without changing a single line of code in "GetRewardPoints()" method? Answer is yes and for that we need extension points.

Extension points can be created using:

  • Implementation inheritance

    1. Virtual : Any class that marks one of its members as virtual is open to extension. In this case mark "GetRewardPoints()" and "CalculateCashback()" as virtual in CreditCard class and then subclass the CreditCard and override the "GetRewardPoints() and "CalculateCashback()"". We can then use polymorphism to supply the client with new version of CreditCard class and have it call the subclass's implementation.

    2. Abstract : Create an abstract base class say "CreditCardAbstract" . Mark GetRewardPoints() and "CalculateCashback()" as abstract and let 2 versions of credit cards inherit from this class. Client depends on abstract base class.

  • Interface inheritance

    • Here client's dependency on class is replaced with interfere. Two version of credit card will provide implementation of this interface.

Advantage of interface inheritance is we can take advantage of many design patterns and that gives flexibility.

The main benefit of this approach is that an interface introduces an additional level of abstraction which enables loose coupling. The implementations of an interface are independent of each other and don’t need to share any code. If you consider it beneficial that two implementations of an interface share some code, you can either use inheritance or composition.

Let's take some examples from tools like Eclipse, Visual Studio, or VS Code etc. There is a vast plethora of tools that can be easily extended without modifying or redeploying them. We extend them by writing plugins.

As per Robert C. Martin (Uncle Bob) , plugin systems are the ultimate consummation, the apotheosis, of the Open-Closed Principle. They are proof positive that open-closed systems are possible, useful, and immensely powerful.

How did these systems manage to close their primary business rules to modification, and yet leave the whole application open to be extended? Simple. They believed in the OCP, and they used the tools of object oriented design to separate high level policy from low level detail. They carefully managed their dependencies, inverting those that crossed architecturally significant boundaries in the wrong direction.

No doubt Uncle Bob is right and he states that the way you get a plugin architecture is to make sure that all dependencies inside the plugin, point at the system; and that nothing in the system points out towards the plugins. The system doesn’t know about the plugins. The plugins know about the system.