Introduction

The Open/Closed Principle (OCP) is one of the most argumentative concepts of the five SOLID principles of object-oriented design, introduced by Bertrand Meyer in 1988. The principle states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means you should be able to add new functionality without changing existing code, which minimizes the risk of introducing new bugs. Being argumentative does not mean it is not important. We should only learn when to use it exactly because you can easily misjudge it.

Problem

Imagine you have a simple e-commerce application with a DiscountCalculator class that applies discounts to orders. Initially, it only supports a flat discount.

public class DiscountCalculator {
    public double calculateDiscount(Order order) {
		    return order.getAmount() * 0.1;
    }
}

But now you need to add a seasonal discount and a loyalty discount. You might jump to an easy fix such as this:

public class DiscountCalculator {
    public double calculateDiscount(Order order, String discountType) {
        if (discountType.equals("FLAT")) {
            return order.getAmount() * 0.1;
        } else if (discountType.equals("SEASONAL")) {
            return order.getAmount() * 0.2;
        } else if (discountType.equals("LOYALTY")) {
            return order.getAmount() * 0.3;
        }
        return 0;
    }
}

Following this approach means whenever any requirement related to discounts change you have to come to the DiscountCalculator class and make your modifications. For example, you can add a new type of discount, remove an existing discount, update the percentage of a particular discount…etc.

This approach can lead to several issues:

  1. Increased risk of bugs: Since each time a new requirement occurs you are coming back to this code and making changes to it, you might unintentionally introduce bugs to other parts of the code you didn’t want to even change.
  2. Difficult maintenance: Imagine when several requirements are added where we have so many types of discounts and some discounts are applied on top of each other while others are not. Putting all the logic in one class will make it harder to read and maintain.
  3. Limited scalability: This is related to point number 2, but the emphasis here on the cognitive complexity of this class when you have so many types of discounts all managed in one place.

This is the problem OCP tries to solve. It pushes you to try to make your code (such as DiscountCalculator in our example) closed for modification (meaning you don’t do any changes on it whenever a specific discount requirement changes).

Solution