{"id":1060,"date":"2015-05-24T11:09:36","date_gmt":"2015-05-24T15:09:36","guid":{"rendered":"http:\/\/springframework.guru\/?p=1060"},"modified":"2019-06-02T12:30:15","modified_gmt":"2019-06-02T16:30:15","slug":"open-closed-principle","status":"publish","type":"page","link":"https:\/\/springframework.guru\/principles-of-object-oriented-design\/open-closed-principle\/","title":{"rendered":"Open Closed Principle"},"content":{"rendered":"<h1>Open Closed Principle<\/h1>\n<p>As applications evolve, changes are required. Changes are required when new functionality is added or existing functionality is updated in the application. Often in both situations, you need to modify the existing code, and that carries the risk of breaking the application&#8217;s functionality. For good application design and the code writing part, you should avoid change in the existing code when requirements change. Instead, you should extend the existing functionality by adding new code to meet the new requirements. You can achieve this by following the Open Closed Principle.<\/p>\n<p>The Open Closed Principle represents the &#8220;O&#8221; of the five <a title=\"SOLID: Principles Of Object Oriented Programming\" href=\"http:\/\/springframework.guru\/solid-principles-object-oriented-programming\/\" target=\"_blank\" rel=\"noopener noreferrer\">SOLID<\/a> software engineering principles to write well-designed code that is more readable, maintainable, and easier to upgrade and modify. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Bertrand_Meyer\" target=\"_blank\" rel=\"noopener noreferrer\">Bertrand Meyer<\/a> coined the term Open Closed Principle, which first appeared in his book <a title=\"Object-Oriented Software Construction\" href=\"http:\/\/www.amazon.com\/Object-Oriented-Software-Construction-CD-ROM-Edition\/dp\/0136291554\" target=\"_blank\" rel=\"noopener noreferrer\">Object-Oriented Software Construction<\/a>, release in 1988. This was about eight years before the initial release of Java.<\/p>\n<p>This principle states: &#8220;<em>software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification<\/em> &#8220;. Let\u2019s zero in on the two key phrases of the statement:<\/p>\n<ol>\n<li>&#8220;<em>Open for extension<\/em> &#8220;: This means that the behavior of a software module, say a class can be extended to make it behave in new and different ways. It is important to note here that the term &#8220;<em>extended<\/em> &#8221; is not limited to inheritance using the Java <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">extend<\/code> keyword. As mentioned earlier, Java did not exist at that time. What it means here is that a module should provide extension points to alter its behavior. One way is to make use of <a title=\"Polymorphism in Java\" href=\"http:\/\/springframework.guru\/polymorphism-java\/\" target=\"_blank\" rel=\"noopener noreferrer\">polymorphism<\/a> to invoke extended behaviors of an object at run time.<\/li>\n<li>&#8220;<em>Closed for modification<\/em> &#8220;: This means that the source code of such a module remains unchanged.<\/li>\n<\/ol>\n<p>It might initially appear that the phrases are conflicting- How can we change the behavior of a module without making changes to it? The answer in Java is abstraction. You can create abstractions (Java interfaces and abstract classes) that are fixed and yet represent an unbounded group of possible behaviors through concrete subclasses.<\/p>\n<p>Before we write code which\u00a0follows the Open\u00a0Closed Principle, let\u2019s look at\u00a0the consequences of violating the Open Closed principle.<\/p>\n<h2>Open Closed Principle Violation (Bad Example)<\/h2>\n<p>Consider an insurance system that validates health insurance claims before approving one. We can follow the complementary <a title=\"Single Responsibility Principle\" href=\"http:\/\/springframework.guru\/single-responsibility-principle\/\" target=\"_blank\" rel=\"noopener noreferrer\">Single Responsibility Principle<\/a> to model this requirement by creating two separate classes. A <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">HealthInsuranceSurveyor<\/code> class responsible to validate claims and a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class responsible to approve claims.<\/p>\n<h4>HealthInsuranceSurveyor.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\npublic class HealthInsuranceSurveyor{\r\n\r\n    public boolean isValidClaim(){\r\n        System.out.println(\"HealthInsuranceSurveyor: Validating health insurance claim...\");\r\n        \/*Logic to validate health insurance claims*\/\r\n        return true;\r\n    }\r\n}\r\n<\/pre>\n<h4>ClaimApprovalManager.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\npublic class ClaimApprovalManager {\r\n\r\n    public void processHealthClaim (HealthInsuranceSurveyor surveyor)\r\n    {\r\n        if(surveyor.isValidClaim()){\r\n            System.out.println(\"ClaimApprovalManager: Valid claim. Currently processing claim for approval....\");\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Both the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">HealthInsuranceSurveyor<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> classes work fine and the design for the insurance system appears perfect until a new requirement to process vehicle insurance claims arises. We now need to include a new <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">VehicleInsuranceSurveyor<\/code> class, and this should not create any problems. But, what we also need is to modify the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class to process vehicle insurance claims. This is how the modified <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> will be:<\/p>\n<h4>Modified ClaimApprovalManager.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\npublic class ClaimApprovalManager {\r\n\r\n    public void processHealthClaim (HealthInsuranceSurveyor surveyor)\r\n    {\r\n        if(surveyor.isValidClaim()){\r\n            System.out.println(\"ClaimApprovalManager: Valid claim. Currently processing claim for approval....\");\r\n        }\r\n    }\r\n\r\n    public void processVehicleClaim (VehicleInsuranceSurveyor surveyor)\r\n    {\r\n        if(surveyor.isValidClaim()){\r\n            System.out.println(\"ClaimApprovalManager: Valid claim. Currently processing claim for approval....\");\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>In the example above, we modified the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class by adding a new <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">processVehicleClaim()<\/code> method to incorporate a new functionality (claim approval of vehicle insurance).<\/p>\n<p>As apparent, this is a clear violation of the Open\u00a0Closed Principle. We need to modify the class to add support for a new functionality. In fact, we violated the Open Closed Principle at the very first instance we wrote the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class. This may appear innocuous in the current example, but consider the consequences in an enterprise application that needs to keep pace with fast changing business demands. For each change, you need to modify, test, and deploy the entire application. That not only makes the application fragile and expensive to extend but also makes it prone to software bugs.<\/p>\n<h2>Coding to the Open\u00a0Closed Principle<\/h2>\n<p>The ideal approach for the insurance claim example would have been to design the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class in a way that it remains:<\/p>\n<ul>\n<li><strong>Open<\/strong> to support more types of insurance claims.<\/li>\n<li><strong>Closed<\/strong> for any modifications whenever support for a new type of claim is added.<\/li>\n<\/ul>\n<p>To achieve this, let\u2019s introduce a layer of abstraction by creating an abstract class to represent different claim validation behaviors. We will name the class <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InsuranceSurveyor<\/code>.<\/p>\n<h4>InsuranceSurveyor.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\n\r\npublic abstract class InsuranceSurveyor {\r\n    public abstract boolean isValidClaim();\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Next, we will write specific classes for each type of claim validation.<\/p>\n<h4>HealthInsuranceSurveyor.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\n\r\npublic class HealthInsuranceSurveyor extends InsuranceSurveyor{\r\n    public boolean isValidClaim(){\r\n        System.out.println(\"HealthInsuranceSurveyor: Validating health insurance claim...\");\r\n        \/*Logic to validate health insurance claims*\/\r\n        return true;\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4>VehicleInsuranceSurveyor.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\n\r\npublic class VehicleInsuranceSurveyor extends InsuranceSurveyor{\r\n    public boolean isValidClaim(){\r\n       System.out.println(\"VehicleInsuranceSurveyor: Validating vehicle insurance claim...\");\r\n        \/*Logic to validate vehicle insurance claims*\/\r\n        return true;\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>In the examples above, we wrote the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">HealthInsuranceSurveyor<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">VehicleInsuranceSurveyor<\/code> classes that extend the abstract <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InsuranceSurveyor<\/code> class. Both classes provide different implementations of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">isValidClaim()<\/code> method. We will now write the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class to follow the Open\/Closed Principle.<\/p>\n<h4>ClaimApprovalManager.java<\/h4>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\n\r\npublic class ClaimApprovalManager {\r\n    public void processClaim(InsuranceSurveyor surveyor){\r\n        if(surveyor.isValidClaim()){\r\n            System.out.println(\"ClaimApprovalManager: Valid claim. Currently processing claim for approval....\");\r\n        }\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>In the example above, we wrote a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">processClaim()<\/code> method to accept a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InsuranceSurveyor<\/code> type instead of specifying a concrete type. In this way, any further addition of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">InsuranceSurveyor<\/code> implementations will not affect the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class. Our insurance system is now <strong>open<\/strong> to support more types of insurance claims and <strong>closed<\/strong> for any modifications whenever a new claim type is added. To test our example, let\u2019s write this unit test.<\/p>\n<h4>ClaimApprovalManagerTest.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.openclosedprinciple;\r\n\r\nimport org.junit.Test;\r\n\r\nimport static org.junit.Assert.*;\r\n\r\n\r\npublic class ClaimApprovalManagerTest {\r\n\r\n    @Test\r\n    public void testProcessClaim() throws Exception {\r\n      HealthInsuranceSurveyor healthInsuranceSurveyor=new HealthInsuranceSurveyor();\r\n      ClaimApprovalManager claim1=new ClaimApprovalManager();\r\n      claim1.processClaim(healthInsuranceSurveyor);\r\n\r\n        VehicleInsuranceSurveyor vehicleInsuranceSurveyor=new VehicleInsuranceSurveyor();\r\n        ClaimApprovalManager claim2=new ClaimApprovalManager();\r\n        claim2.processClaim(vehicleInsuranceSurveyor);\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The output is:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">   .   ____          _            __ _ _\r\n \/\\\\ \/ ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\\r\n( ( )\\___ | '_ | '_| | '_ \\\/ _` | \\ \\ \\ \\\r\n \\\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )\r\n  '  |____| .__|_| |_|_| |_\\__, | \/ \/ \/ \/\r\n =========|_|==============|___\/=\/_\/_\/_\/\r\n :: Spring Boot ::        (v1.2.3.RELEASE)\r\n\r\nRunning guru.springframework.blog.openclosedprinciple.ClaimApprovalManagerTest\r\nHealthInsuranceSurveyor: Validating health insurance claim...\r\nClaimApprovalManager: Valid claim. Currently processing claim for approval....\r\nVehicleInsuranceSurveyor: Validating vehicle insurance claim...\r\nClaimApprovalManager: Valid claim. Currently processing claim for approval....\r\nTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in guru.springframework.blog.openclosedprinciple.ClaimApprovalManagerTest<\/pre>\n<h2>Summary<\/h2>\n<p>Most of the times real closure of a software entity is practically not possible because there is always a chance that a change will violate the closure. For example, in our insurance example, a change in the business rule to process a specific type of claim will require modifying the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ClaimApprovalManager<\/code> class. So, during enterprise application development, even if you might not always manage to write code that satisfies the Open Closed Principle in every aspect, taking the steps towards it will be beneficial as the application evolves.<\/p>\n<h2>Get The\u00a0Code<\/h2>\n<p>I&#8217;ve committed the source code for this post to github. It is a Maven project which you can download and build. If you wish to learn more about the Spring Framework, I have a free introduction to the Spring tutorial. You can sign up for this tutorial in the section below.<\/p>\n\r\n\t<div class=\"df_call_to_action df_content_element cta_square\"  data-cta-class=\"normal\" data-cta-bg-color=\"#0F0F0F\" data-cta-border-color=\"#0F0F0F\">\r\n\t    <div class=\"cta_wrapper\">\r\n\t    \t<div class=\"cta_header\"><h3 style=\"color:#6cb44a !important;\">Source Code<\/h3><\/div>\r\n\t\t    <div class=\"cta_content\">The source code for this post is available on github. You can download it <a title=\"Testing Spring Integration Gateways\" href=\"https:\/\/github.com\/springframeworkguru\/blogposts\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/div>\r\n\t    <\/div>\r\n\t     \r\n\t<\/div>\r\n\n","protected":false},"excerpt":{"rendered":"<p>Open Closed Principle As applications evolve, changes are required. Changes are required when new functionality is added or existing functionality is updated in the application. Often in both situations, you need to modify the existing code, and that carries the risk of breaking the application&#8217;s functionality. For good application design and the code writing part, [&hellip;]<a href=\"https:\/\/springframework.guru\/principles-of-object-oriented-design\/open-closed-principle\/\" class=\"df-link-excerpt\">Continue reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":1099,"parent":774,"menu_order":2,"comment_status":"open","ping_status":"open","template":"","meta":{"_lmt_disableupdate":"","_lmt_disable":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"class_list":["post-1060","page","type-page","status-publish","has-post-thumbnail","hentry"],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/P5BZrZ-h6","_links":{"self":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/pages\/1060"}],"collection":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/comments?post=1060"}],"version-history":[{"count":10,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/pages\/1060\/revisions"}],"predecessor-version":[{"id":5350,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/pages\/1060\/revisions\/5350"}],"up":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/pages\/774"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media\/1099"}],"wp:attachment":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media?parent=1060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}