Liskov Substitution Principle
Tags: javascript, solid
Published: 2017-11-21 19:03:14

---
title: Liskov Substitution Principle
published: true
description: In 1988 Barbara Liskov wrote something that now stands for L in SOLID principles. Let's dive in and learn what is it and how does it relate to TDD.
cover_image: http://d33wubrfki0l68.cloudfront.net/c3704f4b7a4d48ac36187981ca53473beca5a5ae/0f525/assets/images/liskov_substitution_principle.jpg
tags: javascript, solid
---

_Originally posted on [maksimivanov.com](http://maksimivanov.com/posts/liskov-substitution-principle)_


In __1988__ Barbara Liskov wrote something that now stands for __L__ in __SOLID__ principles. Let's dive in and learn what is it and how does it relate to __TDD__.

Here is the original formulation: _"If for each object_ __o1__ _of type_ __S__ _there is an object_ __o2__ _of type_ __T__ _such that for all programs_ __P__ _defined in terms of_ __T___, the behavior of_ __P__ _is unchanged when_ __o1__ _is substituted for_ __o2__ _then_ __S__ _is a subtype of_ __T___."_

Simply speaking: _"Derived class objects must be substitutable for the base class objects. That means objects of the derived class must behave in a manner consistent with the promises made in the base class contract."_

Speaking even more simply: _"Derived class objects should_ __complement___, not_ __substitute__ _base class behavior."_

![liskov example](http://d33wubrfki0l68.cloudfront.net/23d137d68c64df9909d604e3b0e78ffa708dfbec/2f091/assets/images/liskov_1.png)

LSP can also be described as a counter-example of [Duck Test](https://en.wikipedia.org/wiki/Duck_test): _"If it looks like a duck, quacks like a duck, but needs batteries – you probably have the wrong abstraction"_

## So, In Real World

If you have some class __Foo__ and a derived class __SubFoo__, then if you change all the notions of __Foo__ class to __SubFoo__ – the program execution shouldn't change, as __SubFoo__ dosen't change the __Foo__ class functionality, and only extends it.

## Let's See The Example

Getting back to ducks. Let's describe a `Duck`. We have very low expectations on it. We only expect it to be able to quack and nothing else.

```js
describe('Duck', function(){
  describe('#quack', function(){
    it('produces "Quack" sound', function(){
      const duck = new Duck();
      expect(duck.quack()).toEqual('Quack');
    });
  });
});
```

Fine, now lets define the basic duck.

```js
class Duck{
  constructor(){
    // Duck initialization process
  }

  quack(){
    return 'Quack';
  }
}
```

We run the spec and it passes. Cool, now let's create a derived class `MechanicalDuck`. It should also be able to quack. The only difference is that it needs batteries to operate.

```js
class MechanicalDuck extends Duck{
  constructor(battery=null){
    super();
    this._battery = battery;
  }

  quack(){
    if(!this._battery){
      throw 'Need battery to operate.';
    }
    return 'Quack';
  }
}
```

Now according to LSP, we should be able to safely change instances of base class to instances of derived class. Let's change our spec a bit and try to use `MechanicalDuck` instead of `Duck`.

Uh-oh, test failed. `MechanicalDuck` needs battery to quack. So `MechanicalDuck` here is clearly not a duck. Even though it's interface might look similar, it's __behavior__ is totally different.

## But What Would Be A Proper Subclass?

In our case it might be a `FemaleDuck`. Let's implement it.

```js
class FemaleDuck extends Duck{
  constructor(){
    super();
    // Initialization of female stuff
    this._butt = new FemaleDuckButt();
  }

  layAnEgg(){
    const egg = this._butt.layAnEgg();
    return egg;
  } 
}
```

`FemaleDuck` will successfully pass the duck test, as we didn't change the behavior, but only extended it. Our duck can lay eggs, hurray!