How I Cut 80% Effort and Reduced High Risks Using the Open/Closed Principle
The biggest misconception about the Open/Closed Principle I see among young developers today is that it applies only to classes. Well, it's not their fault. They rely on online articles for their learning. Here’s a definition of the Open/Closed Principle from one of those articles:
Objects or entities should be open for extension but closed for modification. This means that a class should be extendable without modifying the class itself.
When they look at this definition, what do they take away from it? They take away that a class should never be modified; instead, it should provide provisions for extension if new functionality needs to be added. And that’s how they miss the true essence of this principle.
A few months ago, I was working on a requirement with my team. Our team was responsible for managing legacy applications that processed orders in the supply chain domain. A requirement was raised for the operations team to use a new process to execute orders alongside the existing process. So, we needed to modify the existing application to support the new process.
An SQL job was responsible for executing orders using the existing process, and we now needed to modify it to support the new operational process as well. The SQL job fetched data from the warehouse and pushed it into a separate database used by the invoicing application. In the new operational process, the data was not being pushed to the invoicing database correctly, resulting in many incorrect values being inserted. That’s why we were working on making the necessary changes to ensure the correct data was inserted.
After extensive debugging and analysis, we made the necessary changes, conducted multiple rounds of testing, and handed it over to users for UAT. As soon as they started testing, they raised issues stating that the new process was working fine, but the existing functionality had broken. We quickly investigated, identified the root causes, and fixed them. They resumed testing, and after a few rounds, they again raised new issues, stating that some scenarios related to the existing operational process had broken. When we discussed the scenarios with them, we realized that we weren’t even aware of those scenarios! We then moved forward, made the necessary changes to support those scenarios, and assigned them for UAT verification. However, after a few rounds of testing, the same issue occurred—more existing scenarios had broken.
At this point, we took a step back and had a detailed discussion with the operations team to understand the full scope of possible workflows. To our surprise, we discovered that numerous cases could be executed depending on various operational conditions. Since there was no dedicated QA team, the responsibility of testing everything ultimately fell on the users. And it didn’t seem feasible for users to test all the scenarios while setting aside their actual work.
My team and I had a brainstorming session to analyze and determine the best approach to this situation. How can we make changes to ensure all scenarios are covered without requiring users to test each one? That’s when we started thinking—why modify the existing SQL job at all? Why not create a separate SQL job to handle the new operational process? The team immediately got to work on developing the new job.
Once the new job was created, we assigned the functionality to users for UAT verification again. This time, everything passed— not a single existing scenario was broken. Why? Because we hadn’t even touched it! A huge amount of effort was saved! The team didn’t have to modify the existing SQL job for the current process. Users didn’t have to test all the existing scenarios. And there was no risk of impacting the existing functionality. A win-win situation!
If you look closely, you’ll see that this is nothing but the Open/Closed Principle in action. We added the new functionality without modifying the existing one. And this is the essence of the Open/Closed Principle. We should start thinking in terms of functionalities rather than just classes, modules, or functions. A functionality can exist in a class, a module, a database job, or a cloud function—it can be any component of the application.
Now, let's rephrase the Open/Closed Principle definition I mentioned at the beginning.
Functionalities should be open for extension but closed for modification. This means that instead of modifying existing functionalities, new ones should be attached or integrated with them.
When we stop modifying existing functionalities and start extending them smartly, we don’t just save effort—we future-proof our systems.
Find me on https://www.linkedin.com/in/gaurav-sharma-unfiltered