OCP: Open/Closed Principle
This is the O of the SOLID series.
Let's start with the Wikipedia definition: In object-oriented programming, the open/closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.
The original Bertrand Meyers definition from 1988 states: software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Bob Martin altered it slightly when he coined the SOLID principles: You should be able to extend the behavior of a system without having to modify that system.
It isn't really possible to add new functionality to a system without adding code somewhere. The Open Closed Principle helps guide us as to where the new code should be added to the system. In a well-designed system functionality can be added without changing existing code. You've used Visual Studio (and probably other software) that allowed extensions or plugins to be added. The host software and those plugins follow the Open Closed Principle. The host software is open for extension – allowing some of its functionality to be changed – while being closed to modification in that those extensions or additional features didn't require changes to the host software to make it happen.
Here's a couple of other ways to think about it.
If software is "open to extension", new behavior can be added without modifying the source code being extended. If software is "closed to extension" the only way to change something is to actually modify that software's code. Think about how difficult it would be if you had to download the source code for Visual Studio in order to make add a feature or extend the tooling that it offered. Visual Studio provides many ways to extend it without ever having to touch its code.
By closing our software to modification, we are less likely to introduce bugs to existing code (since we're not changing existing code), less likely to break dependencies, when fixes are applied, they are often applied to the lowest level possible. As a side benefit, the cyclomatic complexity – number of branches – in a code base often decreases when we open for extension, but close for modification. This is often because the extension points wrap the conditionals instead of the conditional logic being embedded in the source code.
Indicators that the Open/Closed Principle may be Applicable
- Look for switch statements, complicated if, else if logic, or when code is constructing some dependency at runtime based on certain criteria. Often, patterns such as the Factory Pattern or Strategy Pattern are used to help follow the OCP.
- Are you having to change this section of code often?
- Do the needs of this software change runtime? OCP is often implemented using the Strategy Pattern (read about that in other places on the wiki).
- Do requirements change often? You may have started with a concrete implementation that over time has changed. That shift to a more abstract implementation is a clue that perhaps the Open Closed Principle needs to be followed using another pattern for finding the proper concrete implementation at runtime.
Ways the Open Closed Principle be Implemented
- Accept parameters on a method that allows the method to change. Think about a LINQ expression:
someList.Where(item => item.Name.Contains("value"));
TheWhere
extension method accepts a generic function that returnstrue
when matched and otherwisefalse
. That method, not theWhere
method determines what actually gets matched and returned. LINQ is a great example of the Open/Closed principle. - Inherit from an interface or abstract class. Use the base class or the abstract class or interface in the implementation. The concrete implementation is determined or provided at run time based on some criteria.
- Composition or Injection of dependencies.
- Extension Methods. The very nature of extension methods extends the functionality without requiring modification to underlying or original code.
- Prefer implementing new functionality in new classes. Instead of adding more and more methods to an existing class, can the functionality you're developing be isolated?