SOLID Principles: Liskov Substitution Principle (LSP)
Tags: solidprinciples, lsp, liskovsubstitution, coding
Published: 2023-09-11 02:02: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](https://dev.to/amburi/solid-principal-open-closed-principle-ocp-doe)
- **LSP: Liskov Substitution Principle**
- [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:

## Liskov Substitution Principle (LSP)

The Liskov Substitution Principle (LSP) is one of the SOLID principles of object-oriented programming.

**Definition**: Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. 

- Maintain behavioral consistency between base and derived classes.
- Enable subtype polymorphism for flexibility and code reuse.
- Encourage the use of abstract classes, interfaces, and inheritance for better organization and reusability.
- Facilitate software extension without modifying existing code.
- Reduce the risk of introducing bugs when extending the system.
- Support polymorphic behavior, allowing different classes to share a common interface.
- Contribute to robust, maintainable, and extensible software and SOLID compliance.


### Bad Example:

```php
class PaymentGateway {
    public function processPayment($amount) {
        // Common payment processing code
    }
}

class CreditCardPaymentGateway extends PaymentGateway {
    public function processPayment($amount) {
        if ($this->validateCreditCard()) {
            parent::processPayment($amount);
            // Payment successful using credit card
        } else {
            // Payment failed: Invalid credit card
        }
    }
    
    public function validateCreditCard() {
        // Code to validate credit card
    }
}

class PayPalPaymentGateway extends PaymentGateway {
    public function processPayment($amount) {
        // PayPal-specific payment processing code
    }
}

function completePayment(PaymentGateway $gateway, $amount) {
    $gateway->processPayment($amount);
}

$creditCardGateway = new CreditCardPaymentGateway();
$paypalGateway = new PayPalPaymentGateway();

completePayment($creditCardGateway, 100);
completePayment($paypalGateway, 50);
```

Here, the `CreditCardPaymentGateway` class violates the Liskov Substitution Principle. When we try to use it as a substitute for the `PaymentGateway` superclass, it changes the behavior of the `processPayment` method by adding credit card validation logic. This makes it difficult to predict how the program will behave when using different payment gateways, breaking the principle.

### Good Example:

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

class PaymentGateway implements PaymentGatewayInterface {
    public function processPayment($amount) {
        // Common payment processing code
    }
}

class CreditCardPaymentGateway implements PaymentGatewayInterface {
    public function processPayment($amount) {
        // Credit card payment processing code
    }
    
    public function validateCreditCard() {
        // Code to validate credit card
    }
}

class PayPalPaymentGateway implements PaymentGatewayInterface {
    public function processPayment($amount) {
        // PayPal-specific payment processing code
    }
}

function completePayment(PaymentGatewayInterface $gateway, $amount) {
    $gateway->processPayment($amount);
}

$creditCardGateway = new CreditCardPaymentGateway();
$paypalGateway = new PayPalPaymentGateway();

completePayment($creditCardGateway, 100);
completePayment($paypalGateway, 50);
```

Here, we introduce an `PaymentGatewayInterface` interface that all payment gateway classes implement. Each class implements the `processPayment` method as required by the interface. This adheres to the Liskov Substitution Principle because we can freely substitute any payment gateway object in the `completePayment` function without affecting the correctness of the program.

## Wrap-Up!
Liskov Substitution Principle (LSP) is a fundamental principle in object-oriented programming, and it is generally advisable to follow it in most cases. However, there may be exceptional situations, such as performance optimization or dealing with highly complex real-world models, where you need to carefully consider whether strict adherence is practical or whether temporary deviations are warranted for specific reasons. Always document and communicate any intentional deviations from LSP to ensure the maintainability and understanding of your codebase.