Is The Liskov Substitution Principle Really Useful?
Tags: programming, beginners, javascript, codequality
Published: 2021-03-29 18:15:10

Liskov Substitution is part of SOLID Design. **SOLID?**

> SOLID are 5 software development principles or guidelines based on Object-Oriented design making it easier for you to make your projects scalable and maintainable.

Think of them as best practices.

### Now What is Liskov Substitution
You see the **L** in SOLID stands for this principle.

It says
> Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T. **[Barbara Liskov](https://en.wikipedia.org/wiki/Barbara_Liskov)**

Honestly, Too scientific.

In simple terms
> Replacing an instance of a class with its child class should not produce any negative side effects or broken codebase.


#### Meaning
:heavy_check_mark: Can use the subclass of a parent class just the same as using the parent class without breaking anything.
:heavy_check_mark: Subclasses can modify/override parent class methods.
:x: Subclasses can modify the parent's method signature like arguments, return type, and exceptions.
:x: Subclasses can define a new function not present in the parent class.
:x: Parent class can be modified.



### Why do this?
The Goal of this principle is to basically prevent our old codebase from breaking due to new code. This is also in line with the **[Single Responsibility](https://dev.to/huzaifa99/why-you-should-be-following-the-single-responsibility-principle-1h2a)** and the **[Open Close Principle.](https://dev.to/huzaifa99/explained-open-close-principle-in-2-minutes-29dd)**

We will use a simple example for explanation.
### A Simple Use Case
The following example violates the rule.
```javascript
class Animal{
	function eat(){
		// common functionality
		return "Eating Now"	// return type string
	}

	function sleep(){
		// common functionality
		return "I am sleeping"	// return type string
	}
}

class Cat extends Animal{
	function eat(){
		// ... cat specific code
		return "Meow, whatever human"	// return type string
	}

	function sleep(){
		// ... cat specific code

		//  voilating LSP: parnet sleep() does not return boolean
		return true 
	}
}

class Dog extends Animal{
	function eat(){
		// ... dog specific code
		return "Woof, It was tasty."	// return type string
	}

	function sleep(){
		// ... dog specific code
		
		//  voilating LSP: parent sleep() doesn't use Error Exception
		throw Error('I just slept') 
	}
}
```
---
With the Liskov Substitution Principle, we would modify our code as follow
```javascript
class Animal{
	function eat(){
		// common functionality
		return "Eating Now"	// return type string
	}

	function sleep(){
		// common functionality
		return "I am sleeping"	// return type string
	}
}

class Cat extends Animal{
	function eat(){
		// ... cat specific code
		return "Meow, whatever human"	// return type string
	}

	function sleep(){
		// ... cat specific code
		return "I am already sleeping"	// return type string
	}
}

class Dog extends Animal{
	function eat(){
		// ... dog specific code
		return "Woof, It was actually tasty."	// return type string
	}

	function sleep(){
		// ... dog specific code
		return "Zzzzzzzz"	// return type string
	}
}
```
With this approach, we can swap parent and child classes without breaking the code.

### So Is it Helpful?
It is in most cases, but there are those cases where you might want to add some more that does not quite fit in like the **Birds** example below
```javascript
class Bird{
    function fly(){}
}

class Duck extends Bird{}

class Ostrich extends Bird{} // Duck can fly but ostrich cant:
```

So yeah, it really depends. If it's getting over-complicated/over-engineered or is not making sense(like bird example) then it's best to do your own thing.

#### Tip
It's easy to extend old code with new code. You just have to make a new class and extend it with parent/base class without the fear of breaking the already working code. We also get this benefit from **[Dependency Inversion](https://dev.to/huzaifa99/why-the-dependency-inversion-principle-is-worth-using-opj)** principle.


---
So how do you see this? Do you think it's really useful? Be sure to tell me your opinion in the comments.