Dot Net For All

Open Closed Principle Implementation and Use Case

Hello friends, Open Closed principle is the second SOLID principle after single responsibility principle. In this article I will discuss in details about this principle including the implementation using C# code examples. At the end of the article you should be able to implement the principle in your own project.

Open closed principle practical example

As per the open closed principle “Software components should be closed for modification, but open for extension.”

Lets try to understand this misnomer with the help of a practical code example.

Suppose there is a health insurance provider which provides the insurance to the customers. It provides some discount as well to the customers based on the customer loyalty. The code for same scenario is shown in the below snippet.

    public class InsurancePremiumDiscountCalculator
    {
        public int CalculateDiscountPremiumPercent(HealthInsuranceCustomerProfile customer)
        {
            if (customer.IsLoyalCustomer())
                return 20;
            else
                return 0;
        }
    }

    public class HealthInsuranceCustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

Now the same health insurance provider has decided to take over a motor insurance provider. The motor insurance provider already had the same criteria to provide the discount.

Going forward insurance provider wants to provide the discount for both health and motor insurance. Here starts the problem. To achieve this, the developers of the InsurancePremiumDiscountCalculator class change the class structure as below.

The only way out was to add an overloaded method to calculate discount for motor insurance. Further if we want to add Home insurance we may have to change the class once more for the same.

 public class InsurancePremiumDiscountCalculator
    {
        public int CalculateDiscountPremiumPercent(HealthInsuranceCustomerProfile customer)
        {
            if (customer.IsLoyalCustomer())
                return 20;
            else
                return 0;
        }

        public int CalculateDiscountPremiumPercent(MotorInsuranceCustomerProfile customer)
        {
            if (customer.IsLoyalCustomer())
                return 20;
            else
                return 0;
        }
    }

    public class HealthInsuranceCustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

    public class MotorInsuranceCustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

This goes against the open closed principle. We can’t keep changing the master class every time we have to do a add some new functionality.

Open closed principle Implementation

As we can see from the above example, we cannot keep on changing the InsurancePremiumDiscountCalculator class. Finally to circumvent this problem, we should make the InsurancePremiumDiscountCalculator open for extension and closed for modification.

We can achieve the same by introduction of an interface named as ICustomerProfile.

 public class InsurancePremiumDiscountCalculator
    {
        public int CalculateDiscountPremiumPercent(ICustomerProfile customer)
        {
            if (customer.IsLoyalCustomer())
                return 20;
            else
                return 0;
        }
    }

    public class HealthInsuranceCustomerProfile: ICustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

    public class MotorInsuranceCustomerProfile: ICustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

    public class HomeInsuranceCustomerProfile : ICustomerProfile
    {
        public Boolean IsLoyalCustomer()
        {
            //return true or false
            return true;
        }
    }

    public interface ICustomerProfile
    {
        bool IsLoyalCustomer();        
    }

Therefore we can come to some conclusions from this example.

Ease of adding new features. The cost for development of software would be less if we can easily add new features to it. If we don’t use this principle we will keep changing existing code. Therefore spending more time and resources on testing of the new feature.

Hence the above point leads to minimal cost of development and testing.

In addition, we achieved some amount of decoupling while implementing open closed principle. This is closely related to Single Responsibility Principle.

However there is a word of caution, do not keep adding classes blindly. This will result in complex design which would be hard to maintain. For example just to solve a bug don’t try to redesign your class. But if you see some kind of pattern in your bugs which is duplicating in nature, go ahead with refactoring.

This is indeed a subjective decision instead of objective.

Conclusion

In this article we have seen how we can change our class design to have a better implementation of open closed principle with C# code example. Though this principle is programming language agnostic, you might use the same example for other programming languages.

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview