{"id":410,"date":"2026-07-02T12:31:36","date_gmt":"2026-07-02T12:31:36","guid":{"rendered":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/?p=410"},"modified":"2026-07-02T12:38:24","modified_gmt":"2026-07-02T12:38:24","slug":"open-closed-principle","status":"publish","type":"post","link":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/2026\/07\/02\/open-closed-principle\/","title":{"rendered":"Open\/Closed Principle"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">Open for Extension, Closed for Modification<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Definition<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Open\/Closed Principle (OCP)<\/strong> states that software entities (such as classes, modules, or functions) should be <strong>open for extension but closed for modification<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In other words:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we should be able to add new functionality,<\/li>\n\n\n\n<li>we should avoid modifying existing, working code.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Simply put:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Want to add a new feature? Write new code instead of changing code that already works and has been tested.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This means that the behavior of a class can be extended (new capabilities can be added) without having to open it up and modify its existing implementation.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Real-Life Example: How to Understand It?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine a multifunctional kitchen appliance.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you buy it, you get a base unit with a motor and a set of attachments designed for different tasks (a chopping blade, a whisk, etc.).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After some time, you decide that you would like to use the same appliance to juice fruits. You notice that you do not have the appropriate attachment, so you consider grabbing a screwdriver, opening the housing, accessing the motor, removing some screws, and installing new components yourself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Is this approach safe?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Definitely not. In fact, it is unlikely to work because you could damage the motor and cause the appliance to stop functioning altogether.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we want to make juice using the same appliance, we simply go to the store and buy the correct attachment that is designed for that purpose and compatible with the appliance&#8217;s base unit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The base of the kitchen appliance is <strong>closed for modification<\/strong> (we do not tamper with the motor), but the overall system is <strong>open for extension<\/strong> (we can purchase many attachments for different purposes).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Software should work in exactly the same way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The core mechanism of our application should be like the base of the kitchen appliance\u2014stable and untouched\u2014while new features should be like interchangeable attachments.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example \u2014 OCP Violation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose we are building a payment processing system for an online store.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Initially, we support only traditional bank transfers and credit\/debit card payments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>PaymentProcessor<\/code> class below violates OCP:<\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class PaymentProcessor {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void processPayment(String method, double amount) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (method.equalsIgnoreCase(&#8220;CARD&#8221;)) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Card authorization and charging logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Paying by card: &#8221; + amount + &#8221; PLN&#8221;);<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else if (method.equalsIgnoreCase(&#8220;TRANSFER&#8221;)) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Bank transfer processing logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Paying by bank transfer: &#8221; + amount + &#8221; PLN&#8221;);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">The problem appears when the business asks us to add a new payment method, such as BLIK or PayPal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To do that, we must:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the <code>PaymentProcessor<\/code> class.<\/li>\n\n\n\n<li>Add another <code>else if<\/code> block.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Why Is This Bad?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The class is open for modification.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Every time we add a new payment method, we modify the same file. While adding BLIK support, we could accidentally introduce a typo or bug that breaks card payments that have been working perfectly for months.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example \u2014 OCP-Compliant Design<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To fix this code, we need to create a <strong>universal socket<\/strong> (an interface) and <strong>interchangeable attachments<\/strong> (classes implementing specific payment methods).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Create a Universal Socket (Interface)<\/strong><\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">interface PaymentMethod {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 void pay(double amount);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>Create Interchangeable Attachments (Implementations)<\/strong><\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class CardPayment implements PaymentMethod {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void pay(double amount) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Card payment logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Paying by card: &#8221; + amount + &#8221; PLN&#8221;);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class TransferPayment implements PaymentMethod {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void pay(double amount) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Bank transfer logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Paying by bank transfer: &#8221; + amount + &#8221; PLN&#8221;);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>Create a Managing Class \u2014 Closed for Modification<\/strong><\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">lass PaymentProcessor {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void process(PaymentMethod paymentMethod, double amount) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ This class does not know and does not need to know<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ how a particular payment method works.<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ It simply calls pay().<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 paymentMethod.pay(amount);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<h4 class=\"wp-block-heading\">What Do We Gain?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Now, if we want to add BLIK payments, we do not touch a single line of code in <code>PaymentProcessor<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We simply create a brand-new class:<\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class BlikPayment implements PaymentMethod {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void pay(double amount) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ BLIK payment logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Paying with BLIK: &#8221; + amount + &#8221; PLN&#8221;);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">The system has been extended, yet no existing code has been modified.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Open\/Closed Principle has been satisfied.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Why Is OCP Important?<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">Peace of Mind and Safety<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">We do not touch code that is already running in production and generating business value.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This significantly reduces the risk of breaking existing functionality when adding new features.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Less Regression Testing<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Testers do not have to re-test the entire payment system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They only need to test the newly added class (for example, <code>BlikPayment<\/code>).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Better Team Collaboration<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">If five developers need to add five different payment methods, each developer can work on their own file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They do not interfere with one another and create fewer merge conflicts in version control systems such as Git.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Cleaner and More Readable Code<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of having one enormous method filled with dozens of <code>if-else<\/code> statements, we end up with small, focused, and easy-to-understand classes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">When Should You Apply OCP?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Apply OCP when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>you notice repeated <code>if-else<\/code> or <code>switch<\/code> statements that check an object&#8217;s &#8220;type&#8221; and make decisions based on it;<\/li>\n\n\n\n<li>you know that a business requirement will regularly grow with new variants (for example, additional report formats such as PDF, Excel, or CSV; new country-specific tax rules; or new shipping methods);<\/li>\n\n\n\n<li>you are building a plugin-based architecture where users of your code should be able to add their own extensions.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Design your code as if tomorrow a client might ask for a feature that nobody has thought about today.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Open for Extension, Closed for Modification Definition The Open\/Closed Principle (OCP) states that software entities (such as classes, modules, or functions) should be open for extension but closed for modification. In other words: Simply put: Want to add a new feature? Write new code instead of changing code that already works and has been tested. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"saved_in_kubio":false,"footnotes":""},"categories":[12],"tags":[],"class_list":["post-410","post","type-post","status-publish","format-standard","hentry","category-solid"],"_links":{"self":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/410","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/comments?post=410"}],"version-history":[{"count":2,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/410\/revisions"}],"predecessor-version":[{"id":413,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/410\/revisions\/413"}],"wp:attachment":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/media?parent=410"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/categories?post=410"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/tags?post=410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}