A basic explaination of the Open-Closed Principle of software design (one of the five SOLID principles).
Confusion About the Open-Closed Principle
There appears to be some confusion about what it actually is, and how it should be applied:
There appear to be several different interpretation of the principle – some only subtly distinct, others seemingly almost unrelated.Jon Skeet, C# Guru
Why is this principle especially hard to understand?
The principle was devised by B. Meyer and popularized by Robert C. Martin (AKA Uncle Bob). Sadly, Meyer’s text isn’t widely available, and Martin’s explanations are less crisp as his other writing.
The principle is often summarized like this:
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.Bertrand Meyer, quoted on Wikipedia
But this doesn’t help unless we know exactly what is meant by “open”, “closed”, “extension” and “modification”.
The Worst Definition
Based on poor explanation of their ideas, some people seem to think it means:
A class should no change (except to fix bugs), and only inheritance can be used to extend it.
But this definition is misleading in that it appears to misrepresent what Meyer and Martin had in mind. Moreover, in practice it appears to be devastatingly restrictive and, consequentially, downright unhelpful.
A Working Definition
As far as I can tell, the basic idea of the Open Closed Principle is that:
You should be able to extend a module, but changes to a module shouldn’t effect existing clients.
In other words, you create a stable interface – a contract – between modules.
Based on this definition, we can revisit Meyer’s definition. So, by “open for extension” we mean that new functions can added. By “closed to modification”, we mean that those new features won’t modify existing functionality.
Some of the implications of this are that:
- No existing functions can be removed, renamed, have their signatures changed, because then all their clients will break.
- You shouldn’t add a new abstract methods in a class, because then all its descendants will break.
- You can extend a class using, for example, the strategy pattern, inheritance, or by adding new methods.
No software design can ever be completely consistent with this principle and coninue to accommodate changes. The principle is aspirational rather than prescriptive. By their nature, design decisions invariably leave some avenues of extension “closed” and others “open”. This implies that we are required to make best-guesses about future changes based on what we know today. In the words of Kent Beck, “there are no permanently closed abstractions”.