Learning Liskov Substitution Principle by Example
Published: 2021-07-26 15:11:30

Welcome to this third article in which I will show the importance of applying the [**Liskov Substitution Principle**](https://en.wikipedia.org/wiki/Liskov_substitution_principle) when implementing the code of our application.

In the same way as the previous articles talking about the [Single Responsibility Principle](https://dev.to/codbugs/learning-single-responsibility-principle-by-example-593d) and the [Open-Closed Principle](https://dev.to/codbugs/learning-open-closed-principle-by-example-1628), the **advantages** to applying this principle are: code comprehension, component reusability, increased development speed, ease of testability, etc.

**What Liskov Substitution means**

The [**Liskov Substitution Principle**](https://en.wikipedia.org/wiki/Liskov_substitution_principle) is framed within the set of [**SOLID principles**](https://en.wikipedia.org/wiki/SOLID), a set of rules to guide our code in what it's called **Clean Code**. In this case, each letter represents a different principle:

* S for [**Single Responsibility Principle**](https://en.wikipedia.org/wiki/Single-responsibility_principle),
* O for [**Open/Closed Principle**](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle),
* L for [**Liskov SubstitutionPrinciple**](https://en.wikipedia.org/wiki/Liskov_substitution_principle),
* I for [**Interface Segregation Principle**](https://en.wikipedia.org/wiki/Interface_segregation_principle),
* D for [**Dependency Inversion Principle**](https://en.wikipedia.org/wiki/Dependency_inversion_principle)

This principle was established by [Barbara Liskov](https://en.wikipedia.org/wiki/Barbara_Liskov) in 1988:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_What is wanted here is something like the following substitution property: 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._
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

After reading the statement, we could not have clear what it means. So many words, so many general terms may be. If we do some more reads and take care of the sense of the words, we **realized** that the following is the formal sentence of talking about inheritance or **subtyping**:

* We have a program called P,
* P is using an object of type S,
* We also have an object of type T,
* If we change P to use the object of type T and its behavior doesn't change, T is a subtype of S

It's **relevant** to notice that there is **no programming language** mentioned here. So, think more on a **conceptual rule** and take advantage of the programming language selected to apply it.

In my example, as I'm using JavaScript, I like to use functions instead of classes because they are just syntactic sugar to the prototype-based approach. _More information in the [ES6 specification](https://262.ecma-international.org/6.0/#sec-functions-and-classes)_.

**Coding for learning**

I keep working with the code of the [previous article](https://dev.to/codbugs/learning-open-closed-principle-by-example-1628) where we have a `Timer` entity that runs a `Job` entity with a specific frequency. Besides, I added the `Rule` entity to change the behavior of the job depending on the needs.

At this time, we have identified **bugs** in our system when running several jobs. We simulate this by creating a new `Job` entity that throws an error each time it runs. In addition, we want to **register helpful information** about the error. 

In this case, we will implement a new `Timer` entity based on the functionality of the previous one because we want to be **independent of the jobs** executed. We don't want to implement a new way of launching `Job` entities because it is working fine.

So, the approach is to **decorate** the `Jobs` including an error control to avoid a crash in the system. In this case, the `start` method of the existing `Timer` object is responsible for executing the passed `Job`. The new `Timer` entity called `SafeTimer` will **encapsulate** the current job inside a wrapper with the code to control the errors.

As you can imagine from my previous articles, there is a **new entity** in the game called `Decorator`. As I mentioned in the [Learning Single Responsibility Principle by Example](https://dev.to/codbugs/learning-single-responsibility-principle-by-example-593d) article, we need to separate responsibilities and create as many functions or objects as we need to give sense to our code.

Now, the new `ErrorHandlerDecorator` entity comes with the following simple and easy to read code:

```JavaScript
function ErrorHandlerDecorator(method) {
  return function() {
    try {
      method.apply(null, arguments);
    }
    catch(err) {
      // Add any code to inform about the error to the proper log or system
      console.log('error captured');
    }
  };
}
```

The most complex thing to understand is how the `apply` method works. Here I share the [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) to the MDN documentation for this method.

Now, it's time to code the new `SafeTimer` entity. We need to ensure that all errors from any job passed are controlled.

```JavaScript
function SafeTimer(frequency) {
  let timer = new Timer(frequency);

  let originalMethod = timer.start;
  timer.start = function(job) {
    originalMethod(new ErrorHandlerDecorator(job));
  };
  
  return timer;
}
```

I **overwrite** the `start` method but keeping the same definition as we have in our original `Timer` entity.

The code of the `App` entity is changed as well to call to the new `SafeTimer` object implemented and keep the execution of our system safe.

```JavaScript
function App(startAt, endsAt) {
  let frequency = 1; // In seconds

  let timer = new SafeTimer(frequency);
  let rule = new StopTimerWhenNumberIsHigherOrEqualToRule(timer, endsAt);
  let job = new PrintNumbersStartingAtJob(startAt, rule);

  timer.start(job.next);
}
```

More and more functionality based on the entities defined and created can be implemented to cover the requirements and needs to come. For example, change the frequency from seconds to milliseconds, or adding more control when starting and stopping timers.

This article shows how to **evolve the code** of our apps and systems but it doesn't mean that the first time we design the entities we do perfectly fine. **Everything can change and adapt** to a better design and sometimes we probably go up defining and designing super classes or parent objects instead of going down and be more and more specific each round.

**Wrapping up**

This article shows how to evolve our code and its maintainability by applying the  [**Liskov Substitution Principle**](https://en.wikipedia.org/wiki/Liskov_substitution_principle).

It could be something difficult or strange to apply at the beginning if you are not used to it but makes you grow up on how to design the components of your app. Creating objects or classes more abstracts or more specific each time you redesign incurrs in problems of code organization. You're code structure should be something to take care always.

What do you think about the exercise made in this article?
Hope this can be useful to you or just have fun reading it.