Open / Closed Principle
SOLID seems to be the hardest word
- 18 Mar 2017
The Open / Closed Principle (OCP) is, I think, one of the least understood of the SOLID principles; or is the one that gets the least attention. Before I started really thinking about SOLID I would often dismiss the OCP and it would be fair to say that I didn’t really understand it.
So of course me not understanding it, with the big ego and all, naturally I assume others don’t as well? We’ll partly yes. You see I never really questioned my dismissive attitude towards the OCP because nobody else around me paid it all that much attention. Single Responsibility and Dependency Inversion hogged all the attention, then maybe Liskov - but never did any effort or discussions centre around the OCP.
The good / bad name
Bar the Liskov principle, OCP has the least meaningful name of the five principles, and on first glance seems to be pushing two contradictory ideas. The traditional summary for the principle is:
software entities … should be open for extension, but closed for modification SOLID (object-oriented design) - Wikipedia
You should be able to extend your system, but your system should prevent you from modifying it. This is quite a glib simplification of the principle but it’s probably close to the definition I used to hold in my head. The real meaning is derived from older definitions:
- Open systems, in OO design, refer to systems that can be appended to - such as through new classes, methods, etc
- Closed systems, on the other hand, are systems that are available for use, or are in use. Changes to closed systems result in breakages - for example changing a class definition that is used elsewhere breaks those usages
Taking the two together you can see that they’re not mutually exclusive, and really it’s just a obtuse way of saying that you should be able to add new shit to your system without having to modify / break existing shit.
Being closed means being open
So how exactly do you engineer an open system, one that you can extend without going back over existing code? The trick lies in making your system extensible, in ensuring that you can add to the system without negative side-effects. While this sounds like a tall ask there’s a set of principles that exists which promote exactly this - they’re called the SOLID principles.
You see when you’re trying to compose a system that adheres to the OCP you’ll likely find that they ways you close off ‘in use’ code from modification, or open up systems for extension, both draw from the remaining four S-LID principles.
- The SRP decomposes your classes along sensible lines - making it far less likely that you’ll need to impact multiple responsibilities when adding to your system. It also introduces a smaller unit of change should you need to replace the implementation of a responsibility
- Liskov helps guarantee predictable behavior between subtypes of a common base. This provides an avenue for substitution when extending the system - ie: there’s no need to rewrite a module if you can substitute in an alternative implementation and not break consuming code
- Interface Segregation reduces cohesion which in turn reduces the scope that an extension requires modifications to code. It keeps unnecessary details out of interfaces reducing the cost of creating new implementations, and protecting the existing system from faulty implementations of unneeded interface methods
- The Dependency Inversion Principle removes direct reliance on specific implementations allowing you to substitute in alternative Liskov compliant implementations
In combination these principles allow you to engineer code that does not require any modifications - in the closed principle sense. New features can always be added through re-implementations of interfaces / abstractions leaving existing ‘in use’ code untouched.
Benefits
By removing the need to modify existing code the OCP removes the potential to introduce regression bugs or side-effects into stable / in-use functionality. It is the opposite of the all too common spaghetti code where you make a seemingly innocent change and unwittingly bring down some unrelated functionality.
OCP compliment systems should also be, in theory, faster to extend as they quite literally built to support extension.
Faster feature turn around and less bugs sounds quite appealing doesn’t it? The reality however is somewhat different and it really depends on how far you go to make your code OCP - full compliance may not necessarily yield fruitful benefits due to the time cost required to create and maintain high code standards.