This principle states the most fundamental rule to make your software flexible. All other OOP principles, methodologies and conventions revolve around this principle. Open-Closed Principle (OCP) states:
Software entities should be open for extension, but closed for modification.
At first glance, it seems self-contradicting. Lets define the following terms to get more clarity:
- Software entities are functions, methods, modules, classes in the design.
- Open for extension means that its behaviour can be extended or changed depending
- Closed for modification restricts changing source code of the module for extending or changing its behaviour.
Open for extension attribute addresses the real need of softwares to change with time as business requirements change. This change though, should not cause the source code to change. Why? We can realise its advantage as soon as we consider a code consisting of if-then-else logic. Lets consider the logging example, which we had considered in Dependency Inversion Principle.
logger module:
form_message
write_message_to_file
The business now requires that the logging should be done to the database, rather than a file. So here goes the new logic:
logger module:
form_message
if target is file
write_message_to_file
else
write_message_to_db
endif
It works, definitely works. The problem is that in future if the requirements change again to log in a, say XML file, the source code will have to be changed again. Any change in the source code might not only insert bugs but also increase the amount of testing to be done to make sure it works fine and does not break anything. Especially if this change has to be done in the core part of a design, entire testing suites might have to be executed. Open-Closed Principle advocates making the software flexible by incremental code, add code rather than change code.
Abstraction
The answer, again, is abstraction. Abstraction enables you to have an interface which separates the intent from the implementation, or the what from the how. This opens possibilities for multiple hows for the same what.
In languages with syntactical support for OOP, like C++, Java, Python, Ruby, and many more; this can be done using interface or implementation inheritance. Multiple forms of the same object is possible through polymorphism.
The above algorithm can be converted to:
logger module:
form_message
write_message(target)
target:
write
file derived from target:
write: write_to_file
db derived from target:
write: write_to_db
If logging has to be moved to XML file, then we can simply add another target derivative:
xmlfile derived from target:
write: write_to_xmlfile
The logger modules does not have to change to add a new destination for logging. This is open for extension but closed for modification.
A module cannot be completely closed against all changes. If some of its core logic has to be changed, then the module code will have to changed. However, the module should be closed for extensions, it should provide alternative ways of extending itself.
Corollaries
This rule has branched into lot of corollaries or design conventions. The two most popular ones are:
- All member variables should be private. This is prompted from the fact that a closure cannot be enforced if the member variable can be accessed directly, leaving possibility for violation of OCP. Every member variable should be private and its access should be controlled by appropriate methods.
- No global variables. Global variables are dangerous because they are accessible to everyone, and available for writing. Someone can inadverently write into a global variable which can crash the whole system.
We can define some coding practices like avoid multiple if-then-else or switch-case statements.
Following links present code examples for this design principle:
Related Posts:
Back to Design Principles.
Technorati tags: open-closed principle, design principle, object oriented, abstraction, polymorphism, open for extension, closed for modification
Copyright Abhijit Nadgouda.


April 8th, 2006 at 5:11 am
[...] Even though most of the class design principles advocate loose coupling between classes, so that they can change without affecting the other, dependencies between classes cannot be avoided. CCP tries to look at classes that are dependent on each other from a code change perspective. Even though Open-Closed Principle (OCP) recomments full closure to code change, it is not always possible. Sometimes some of the class design principles are violated consciously to improve performance, just like denormalization in databases. However this violation should be a conscious decision and the product should be ready for changes because of it. [...]
April 8th, 2006 at 7:20 am
[...] Open-Closed Principle (OCP) [...]
August 28th, 2006 at 12:00 am
[...] Open-Closed Principle (OCP) [...]
November 6th, 2006 at 9:04 pm
[...] The Open-Closed Principle is the heart of OO design. It advocates for abstraction to provide extensibility to any object, which is typically implemented using inheritance. Inheritance itself can lead to many possibilities, some of which can lead to wrong design. Liskov Substitution Principle (LSP) (pdf) is a guideline for inheritance design: What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. [...]
November 13th, 2006 at 6:36 pm
[...] Even though most of the class design principles advocate loose coupling between classes, so that they can change without affecting the other, dependencies between classes cannot be avoided. CCP tries to look at classes that are dependent on each other from a code change perspective. Even though Open-Closed Principle (OCP) recomments full closure to code change, it is not always possible. Sometimes some of the class design principles are violated consciously to improve performance, just like denormalization in databases. However this violation should be a conscious decision and the product should be ready for changes because of it. [...]
December 2nd, 2006 at 10:51 am
[...] The key is that the interface abstraction is designed using the hook system. Node is the abstraction for any content type. The core of Drupal system uses these abstractions and is hence able to handle any extended content types without code modification. The use of node_invoke() to invoke any node hook. This means that the interface for communication with any node is designed using this abstraction. Node and hook system together enable Drupal to comply with Open-Closed Principle. [...]