Logo

dev-resources.site

for different kinds of informations.

Open/Closed Principle (OCP)

Published at
12/8/2024
Categories
solidprinciples
Author
mofshamim
Categories
1 categories in total
solidprinciples
open
Author
9 person written this
mofshamim
open
Open/Closed Principle (OCP)

Software entities (classes, modules, functions) should be open for extension but closed for modification.

This means:
Open for Extension: You should be able to add new functionality to an existing module or class without altering its existing code.

Closed for Modification: Once a class is written and tested, you should not need to modify it to add new functionality.

Why is OCP Important?

  • Preserves Stability: Existing code remains untouched, reducing the risk of introducing new bugs.

  • Enhances Flexibility: Makes the system adaptable to new requirements without rewriting or breaking existing logic.

  • Supports Scalability: New behaviors can be added with minimal effort.

  • Aligns with Agile Practices: Easily adapts to changing requirements, a common scenario in software development.


How Violates OCP?

OCP is violated when:

  • Adding new behavior requires modifying existing classes or methods.
  • This leads to tight coupling, making it harder to maintain or extend the system.

Example of OCP Violation:
Imagine a PaymentProcessorclass that handles different payment methods:

public class PaymentProcessor
{
    public void ProcessPayment(string paymentType, decimal amount)
    {
        if (paymentType == "CreditCard")
        {
            Console.WriteLine($"Processing credit card payment of {amount:C}.");
        }
        else if (paymentType == "Cash")
        {
            Console.WriteLine($"Processing cash payment of {amount:C}.");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Problems:

  • Adding a new payment type requires modifying the ProcessPayment method.
  • Every change increases the likelihood of bugs in existing functionality.
  • This violates OCP because the class is not closed for modification.

How to Implement Class-Level OCP

OCP can be implemented using techniques like polymorphism, composition, and strategy patterns. Below are steps for implementation using class-level OCP with execution flow.

Step 1: Define an Abstraction
Create an abstract class or interface to define common behavior.

public interface IPaymentProcessor
{
    void ProcessPayment(decimal amount);
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Concrete Implementations
Implement the interface for each payment type.

public class CreditCardProcessor : IPaymentProcessor
{
    public void ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing credit card payment of {amount:C}.");
    }
}

public class CashPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(decimal amount)
    {
        if (amount > 1000)
        {
            Console.WriteLine("Cash payment cannot exceed $1000.");
            return;
        }
        Console.WriteLine($"Processing cash payment of {amount:C}.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Use Abstraction in the Client
The client depends on the abstraction (IPaymentProcessor) and can dynamically work with any implementation.

public class PaymentHandler
{
    private readonly IPaymentProcessor _paymentProcessor;

    public PaymentHandler(IPaymentProcessor paymentProcessor)
    {
        _paymentProcessor = paymentProcessor;
    }

    public void HandlePayment(decimal amount)
    {
        _paymentProcessor.ProcessPayment(amount);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Call PaymentHandler
Create and use the appropriate payment processor at runtime.

var creditCardProcessor = new CreditCardProcessor();
var paymentHandler = new PaymentHandler(creditCardProcessor);
paymentHandler.HandlePayment(500);

var cashProcessor = new CashPaymentProcessor();
var cashPaymentHandler = new PaymentHandler(cashProcessor);
cashPaymentHandler.HandlePayment(1200);
Enter fullscreen mode Exit fullscreen mode

Execution Flow

  • The PaymentHandlerrelies on the IPaymentProcessorinterface.
  • Adding a new payment type (e.g., DigitalWalletProcessor) requires creating a new class that implements IPaymentProcessor.
  • No changes are made to the existing PaymentHandleror other classes.

How to Implement Method-Level OCP

For finer-grained control (specific method behavior), we can use strategies or composition to inject new logic into a method.

Example: Discount Calculation

public interface IDiscountStrategy
{
    decimal CalculateDiscount(decimal price);
}

public class RegularDiscount : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal price) => price * 0.1m; // 10% discount
}

public class VIPDiscount : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal price) => price * 0.2m; // 20% discount
}

public class DiscountCalculator
{
    public decimal Calculate(decimal price, IDiscountStrategy discountStrategy)
    {
        return discountStrategy.CalculateDiscount(price);
    }
}

Enter fullscreen mode Exit fullscreen mode

Usage:

var calculator = new DiscountCalculator();
decimal discountedPrice = calculator.Calculate(1000, new VIPDiscount());
Console.WriteLine($"Discounted Price: {discountedPrice:C}");

Enter fullscreen mode Exit fullscreen mode

Flow:
New discount types can be added without modifying the DiscountCalculator.

By following OCP, you build systems that are easier to extend and maintain while reducing risks of breaking existing functionality.

solidprinciples Article's
30 articles in total
Favicon
ISP - O Princípio da Segregação de Interface
Favicon
Disadvantages of the Single Responsibility Principle(SRP)
Favicon
Guia: O que é SOLID
Favicon
Interface Segregation Principle (ISP)
Favicon
Dependency Inversion Principle (DIP)
Favicon
Liskov Substitution Principle (LSP)
Favicon
Create your own Logger using Open-closed principle
Favicon
SOLID: Dependency Inversion Principle (DIP) in C#
Favicon
SOLID: Principio de Abierto/Cerrado
Favicon
LSP - O Princípio da Substituição de Liskov
Favicon
SOLID: Principio de Responsabilidad Única
Favicon
SOLID Principles for React / React Native Development
Favicon
Single Responsibility Principle (SRP)
Favicon
Solid Prensipleri
Favicon
Mastering SOLID Principles in .NET Core: A Path to Clean and Scalable Code
Favicon
OCP - O Princípio Aberto/Fechado
Favicon
SRP - O Princípio da Responsabilidade Única
Favicon
SOLID Design Principles
Favicon
Rethinking interfaces in Flutter projects
Favicon
Understanding the SOLID Principles in PHP and How They Improve Code Quality
Favicon
SOLID: The Liskov Substitution Principle (LSP) in C#
Favicon
Is Clean Code really practical?
Favicon
Open/Closed Principle (OCP)
Favicon
Single Responsibility Principle (SRP)
Favicon
Solid Principle in Simple English
Favicon
Why Clean Architecture and SOLID Principles Should Be the Foundation of Your Next Project!
Favicon
Seja um desenvolvedor melhor com S.O.L.I.D.
Favicon
SOLID: Open-Closed Principle (OCP) in C#
Favicon
SOLID Principles Explained in a Simple Way 🛠️✨ with Real-Life Examples
Favicon
Object Oriented Design Balance With Understanding Anti-Single Responsibility Principle

Featured ones: