👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
Open Closed Principle in SOLID

Open Closed Principle in SOLID

Author - Abdul Rahman (Content Writer)

SOLID

6 Articles

Improve

Table of Contents

  1. What we gonna do?
  2. Why we gonna do?
  3. How we gonna do?
  4. Summary

What we gonna do?

In this article, let's learn about Open Closed Principle in SOLID Principles in .NET.

Note: If you have not done so already, I recommend you read the article on Single Responsibility Principle in SOLID.

Why we gonna do?

The Open Closed Principle (OCP) is a fundamental principle of SOLID. The OCP states that software entities should be open to extension but closed to modification.

We all are using OCP principle in DTO's / POCO's without even knowing that we are using it. In API's we send back response to client using DTO. Once clients start to consume, we cannot remove a property from DTO as it might break the clients which means closed for modification. But we add new property to DTO to send new data / information to clients which means open for extension.

The Open Closed Principle should be applied to any software entity that is likely to change over time. This includes classes, methods, and interfaces. When designing software, it is essential to consider the possibility of future changes, and the OCP helps to future-proof our codebase.

How we gonna do?

Let's see a practical C# example of the Open Closed Principle using a tax calculation scenario. Here, we define an interface ITaxCalculator and provide different implementations for inclusive and exclusive tax modes. This allows us to add new tax calculation strategies without modifying the existing code.


public interface ITaxCalculator
{
    bool CanHandle(string taxMode);
    (Money baseAmount, Money taxAmount) GetTax(Money baseAmount, TaxPercentage taxPercentage);
}

public sealed class InclusiveTaxCalculator : ITaxCalculator
{
    public bool CanHandle(string taxMode)
    {
        return taxMode.Equals("Inclusive", StringComparison.InvariantCultureIgnoreCase);
    }

    public (Money baseAmount, Money taxAmount) GetTax(Money baseAmount, TaxPercentage taxPercentage)
    {
        // Calculate the tax amount based on the inclusive tax percentage
        return (baseAmount, netTaxAmount);
    }
}

public sealed class ExclusiveTaxCalculator : ITaxCalculator
{
    public bool CanHandle(string taxMode)
    {
        return taxMode.Equals("Exclusive", StringComparison.InvariantCultureIgnoreCase);
    }

    public (Money baseAmount, Money taxAmount) GetTax(Money baseAmount, TaxPercentage taxPercentage)
    {
        // Calculate the tax amount based on the exclusive tax percentage

        return (baseAmount, netTaxAmount);
    }
}

public sealed class NullTaxCalculator : ITaxCalculator
{
    public bool CanHandle(string taxMode)
    {
        return true;
    }

    public (Money baseAmount, Money taxAmount) GetTax(Money baseAmount, TaxPercentage taxPercentage)
    {
        return (baseAmount, Money.Create(0).Value);
    }
}
      

Now create a factory class TaxCalculatorFactory that will return the appropriate tax calculator based on the tax mode.


public class TaxCalculatorFactory
{
    private readonly IEnumerable<ITaxCalculator> _taxCalculators;

    public TaxCalculatorFactory(IEnumerable<ITaxCalculator> taxCalculators)
    {
        _taxCalculators = taxCalculators;
    }

    public ITaxCalculator GetTaxCalculator(string taxMode)
    {
        return _taxCalculators.FirstOrDefault(x => x.CanHandle(taxMode), new NullTaxCalculator());
    }
}
      

The TaxCalculatorFactory class takes a collection of ITaxCalculator implementations and uses the CanHandle method to determine which calculator to use based on the provided tax mode. If no matching calculator is found, it returns a NullTaxCalculator.

Finally you need to register these in DI container.


public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ITaxCalculator, InclusiveTaxCalculator>();
    services.AddScoped<ITaxCalculator, ExclusiveTaxCalculator>();
    services.AddScoped<TaxCalculatorFactory>();
}
      

Now you can inject TaxCalculatorFactory in your class and use it to get the appropriate tax calculator based on the tax mode.

By following the Open Closed Principle, you can add new tax calculation strategies (like a new tax mode) by simply creating a new class that implements ITaxCalculator, without modifying the existing code. This keeps your codebase flexible and easy to extend.

Summary

Advantages of Open Closed Principle:

  • Testability: Makes code more testable by reducing the need for regression testing when making changes. This allows for faster and more efficient testing.
  • Maintainability: Makes code more maintainable by reducing the risk of introducing bugs and breaking existing functionality when making changes.
  • Reusability: By designing software entities to be open to extension but closed to modification, we can create more reusable code.
  • Scalability: By allowing software entities to be extended without modifying the existing code, the OCP makes code more scalable and adaptable to changing requirements.
  • Better Teamwork: Team members can work on different parts of the system simultaneously without interfering with each other's work. This leads to more efficient teamwork and a more efficient development process.

The Open Closed Principle is an essential principle of object-oriented design that states that software entities should be open to extension but closed to modification. By following this principle, we can ensure that our software is more maintainable, scalable, and adaptable to changing requirements. The use of abstraction, inheritance, and interfaces allows us to extend our software entities without modifying the existing code, reducing the risk of introducing bugs and breaking existing functionality. By following the OCP, we can create more flexible, maintainable, and robust codebases that are easier to test and scale.

👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
  • SOLID
  • OCP
  • Open Closed