SOLID Principles: Open-Closed Principle (OCP)
Tags: solidprinciples, openclosedprinciple, ocp, architecture
Published: 2023-09-10 00:50:32

## 🪨 SOLID Principles

[**SOLID**](https://dev.to/amburi/solid-principles-3jpo) is a list of 5 software engineering principles. It is a meta acronym where each letter corresponds to another acronym:

- [SRP: Single Responsibility Principle](https://dev.to/amburi/solid-principles-single-responsibility-principle-srp-4bfm)
- **OCP: Open-Closed Principle**
- [LSP: Liskov Substitution Principle](https://dev.to/amburi/solid-principles-liskov-substitution-principle-lsp-1pco)
- [ISP: Interface Segregation Principle](https://dev.to/amburi/solid-principles-interface-segregation-principle-isp-bbf)
- [DIP: Dependency Inversion Principle](https://dev.to/amburi/solid-principles-dependency-inversion-principle-dip-1cpk)

Without any further ado, let's jump into today's topic:

## Open-Closed Principle (OCP)
The Open-Closed Principle (OCP) is one of the SOLID principles of object-oriented programming.

**Definition**: Software entities like classes, modules, functions, etc., should be open for extension but closed for modification.

- The "open" part says: We should only extend existing code to introduce new functionality.
- The "closed" part says: Once a module has been developed and tested, the code should only be changed to correct bugs.

**Goal**: Reduce the risk of introducing errors or unintended side effects when making changes.

**Advantages**:

- Modularized and improved flexibility in software system design.
- Make software systems easier to maintain and extend.
- Improves code reusability 
- Allows the creation of new features through composition and inheritance rather than modification.

### Bad example:

```php
class PaymentProcessor {
    public function processPayment($amount, $method) {
        if ($method === 'credit_card') {
            // Code to process credit card payment
          } elseif ($method === 'paypal') {
            // Code to process PayPal payment
        } else {
            throw new \InvalidArgumentException("Invalid payment method: $method");
        }
    }
}
```

Here, the `PaymentProcessor` class is not closed for modification. If we want to add a new payment method, we must modify the `processPayment` method, which violates the Open-Closed Principle.

This design makes the code brittle and requires changes to existing code whenever a new payment method is introduced.

### Good example:

```php
interface PaymentMethod {
    public function processPayment($amount);
}

class CreditCardPayment implements PaymentMethod {
    public function processPayment($amount) {
        // Code to process credit card payment
    }
}

class PayPalPayment implements PaymentMethod {
    public function processPayment($amount) {
        // Code to process PayPal payment
    }
}

class PaymentProcessor {
    private $paymentMethod;

    public function __construct(PaymentMethod $paymentMethod) {
        $this->paymentMethod = $paymentMethod;
    }

    public function processPayment($amount) {
        $this->paymentMethod->processPayment($amount);
    }
}
```

Here, we've created a `PaymentMethod` interface that defines the `processPayment` method. Each payment method (e.g., Credit Card and PayPal) implements this interface. The `PaymentProcessor` class is now open for extension but closed for modification. We can add new payment methods by creating classes implementing the `PaymentMethod` interface without changing the existing code.

## Wrap-Up!
As a software developer, I sometimes struggle to keep the Open-Closed Principle (OCP) due to legacy code, adding layers that bring performance concerns, changing requirements, the need for abstraction, and uncertainty about future changes. It is crucial to carefully consider when and where to apply OCP to strike the right balance between flexibility and maintainability.

Happy Coding!