SOLID Design Principles: Learn the Liskov-Substitution Principle
Tags: python, solidprinciples, cleancode, programming
Published: 2023-11-25 11:01:54

👋 Hey there, fellow software enthusiasts!

I'm Revisto, a passionate software engineer 👨‍💻, and I want to dive into the exciting world of SOLID principles.

**SOLID** is a set of rules and principles that help us create maintainable, reusable, and flexible software designs. These principles guide us in building software that can adapt and grow as our projects evolve. Today, we will focus on the third principle of SOLID.

- S: [Single Responsibility Principle](https://dev.to/revisto/solid-design-principles-learn-the-single-responsibility-principle-3cb1)
- O: [Open-Closed Principle](https://dev.to/revisto/solid-design-principles-learn-the-open-closed-principle-2o8o)
- **L: Liskov Substitution Principle**
- I: Interface Segregation Principle
- D: Dependency Inversion Principle



✨ The Liskov Substitution Principle is named after the brilliant [Barbara Liskov](https://en.wikipedia.org/wiki/Barbara_Liskov). Simply put, it states that **a child class should be able to replace its parent class seamlessly**. This means that objects of the child class should be able to substitute objects of the parent class without causing any issues or breaking the application's integrity.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co1y7jp9h7mhgjl00b3q.jpg)




In other words, any piece of code that interacts with objects of a specific type should continue to function correctly even when those objects are replaced with instances of a subtype.

> Subtypes must be substitutable for their base types.

(A subtype can be either a class extending another class or a class implementing an interface.)

Let's consider an example to better grasp the concept. Imagine we have a Teleportation class in our codebase. According to the Liskov Substitution Principle, we should be able to substitute the Teleportation class with any of its subclasses, such as Car, Bike or Cycle, without causing any issues or breaking the existing code🤩.


## 📔 Example

```python
from abc import ABC, abstractmethod

class TransporationDevice(ABC):
        @abstractmethod
        def start_engine(self):
            pass

class Car(TransporationDevice):
        def start_engine(self):
           print("Starting Engine...")

class Bike(TransporationDevice):
        def start_engine(self):
           print("Starting Engine...")

class Cycle(TransporationDevice):
        def start_engine(self):
          # Bicyles don't have engines
          raise NotImplementedError()
```
❌ The `TransporationDevice` class doesn't adhere to the Liskov Substitution Principle. When we think about scaling, there is a problem because not all the devices have engines and then there would be a problem.
When that happens, the TransporationDevice class needs to change to support all devices and use other classes for all teleportation kinds. Thus, the current design violates OCP.

```python
from abc import ABC, abstractmethod

class TransporationDevice(ABC):
    @abstractmethod
    def start(self):
        """Steps to start the vehicle"""

class TransporationDeviceWithoutEngine(ABC):
    pass

class TransporationDeviceWithEngine(ABC):        
    @abstractmethod
    def start_engine(self):
        """Process to start the engine"""

class Car(TransporationDeviceWithEngine):

        def start(self):
            # First start engine
            self.start_engine()
            # Do other steps here

        def start_engine(self):
           print("Starting Engine...")

class Bike(TransporationDeviceWithEngine):
        def start(self):
            # First start the engine
            self.start_engine()
            # Do other steps here

        def start_engine(self):
           print("Starting Engine...")


class Cycle(TransporationDeviceWithoutEngine):
        def start(self):
            print("Hit pedals....")
```

More examples at [my GitHub](https://github.com/Revisto/SOLID/tree/master/liskov-substitution)


## Benefits of Applying LSP:
By adhering to the Liskov Substitution Principle, we can ensure that our code remains **flexible and robust**. It **reduces the chances of introducing bugs or errors when extending our codebase**.


🚀 Stay tuned for more articles where we'll explore the other SOLID principles and delve into the exciting world of software engineering.

Thanks for reading. Feel free to comment your thoughts😊. Hope this post was helpful. You can hit me up on [Linked In](https://www.linkedin.com/in/revisto/) and [Github](https://www.github.com/revisto/).

Happy coding!