Open / Closed Principle

The Open/Closed Principle (OCP) states that all classes should be open for extension but closed for modification. “Open for extension” means that the design of your class should allow adding new functionality as new requirements are generated. “Closed for modification” means that once you have developed the class, you should never modify it, unless you need to fix bugs.

Even the two parts of the principle appear to be opposite, if you structure your code correctly, you should be able to add functionality without editing existing code. How you achieve this ? Your design should reply on abstractions for dependencies, such as interfaces or abstract classes, rather than using concrete implementation. New functionality can be added by adding new classes than implement the interfaces.

The first benefit of OCP to your code is that you don’t need to change the existing code, once it was written, tested, documented. So you reduce the risk on adding bugs into existing code. Another benefit of using contracts is loose coupling and increased flexibility.

ocpSource: Solid motivational pictures

Let’s consider the GoldPriceAlert class from previous article with the extra feature to allow user to decide the way to be notified: console, email, sms.

The above sample code is a basic module for logging alerts. As you can see if you decide to implement the SMS logging type, you need to modify the GoldPriceAlert method. This violates the OCP.

We can easily refactor the code to achieve the OCP by removing the enum LogType that limits the types of alerts. Then we’ll create a class for each type of logger. Additional log types can be added later without changing any existing code.

The logger class still performs all logging but using one of the classes described earlier. In order that the classes are loose coupled, each message logger type implements ILog interface. The GoldPriceAlert class is never aware of the type of the logger being used as the dependency is provided as an ILog instance using constructor injection.

The refactored code: