SOLID principles using Typescript

SOLID principles using TypescriptSOLID principles using Typescript

The following article explains SOLID principles using Typescript.

Here are more articles about Typescript:

Introducing Typescript

Introducing Typescript: Language features

SOLID is an acronym for the first five object-oriented design(OOD) principles by Robert C. Martin, popularly known as @UncleBob.

The five SOLID principles are:

  • Single responsibility principle: a class should have one, and only one, reason to change;
  • Open-closed principle: it should be possible to extend the behavoir of a class without  modifying it;
  • Liskov Substitution principle: subclasses should be substitutable for their superclasses;
  • Interface segregation principle: many small, client-specific interfaces are better than one general purpose interface;
  • Dependency inversion principle: depends on abstractions not concretions;

These principles, make it easy for a programmer to develop software that are easy to maintain and extend. They also make it easy for developers to avoid code smells, easily refactor code, and are also a part of the agile or adaptive software development.

The Single Responsibility Principle (SRP)

The SRP requires that a class should have only one reason to change. A class that follows this principle performs just few related tasks. You don’t need to limit your thinking to classes when considering the SRP. You can apply the principle to methods or modules, ensuring that they do just one thing and therefore have just one reason to change.

 

Example – wrong way

The class Task defines properties related to the model, but it also defines the data access method to save the entity on a generic data source:

UML

 

SOLID principles using Typescript - SRP wrong way

Code

Example – right way

The  Task class can be divided between Task class, that takes care of model description and TaskRepository that is responsabile for storing the data.

UML

 

SOLID principles using Typescript - SRP right way

Code

 

The Open-closed Princple (OCP)

 Software entities should be open for extension but closed for modification.

The risk of changing an existing class is that you will introduce  an inadvertent change in behaviour. The solution is create another class that overrides the behaviour of  the original class. By following the OCP, a component is more likely to contain maintainable and re-usable code.

Example – right way

The CreditCard class describes a method to calculate the monthlyDiscount(). The monthlyDiscount() depends on the type of Card, which can be : Silver or Gold. To change the monthly discount calc, you should create another class which overrides the monthlyDiscount() Method.

The solution is to create two new classes: one for each type of card.

UML

SOLID principles using Typescript - OCP Right

Code

The Liskov Substitution Principle (LSP)

Child classes should never break the parent class’ type definitions.

The concept of this principle was introduced by Barbara Liskov in a 1987 conference keynote and later published in a paper together with Jannette Wing in 1994.

As simple as that, a subclass should override the parent class methods in a way that does not break functionality from a client’s point of view.

Example

In the following example ItalyPostalAddress, UKPostalAddress and USAPostalAddress extend one common class: PostalAddress.

The AddressWriter class refers PostalAddress: the writer parameter can be of three different sub-types.

UML

SOLID principles using Typescript - LSP Right

Code

The Interface Segregation Principle (ISP)

It is quite common to find that an interface is in essence just a description of an entire class. The ISP states that we should write a series of smaller and more specific interfaces that are implemented by the class. Each interface provides an single behavior.

 

Example – wrong way

The following Printer interface makes it impossible to implement a printer that can print and copy, but not staple:

Example – right way

The following example shows an alternative approach that groups methods into more specific interfaces. It describe a number of contracts that could be implemented individually by a simple printer or simple copier or by a super printer:

The Dependency inversion principle (DIP)

The DIP simply states that high-level classes shouldn’t depend on  low-level components, but instead depend on an abstraction.

Example – wrong way

The high-level WindowSwitch depends on the lower-level CarWindow class:

UML

SOLID principles using Typescript - DIP wrong way

Code

Example – right way

To follow the DIP, the class WindowSwitch should references an interface (IWindow) that is implemented by the object CarWindow:

UML
SOLID principles using Typescript - DIP right way

Code

Final thoughts

Typescript make it possible to bring all of the principles and practices of OOP into your software, using SOLID principles to guide your design patterns.

Here’s the GitHub repository containing the full examples.

About Samuele Resca

Samuele Resca is an Microsoft MVP Visual Studio and Development Technologies, Software Engineer, specializing mainly on ASP.NET MVC and in general about everything that revolves around the web. Samuele was born in 1994, and works as a software developer @ YOOX NET-A-PORTER Group He loves the MVC frameworks, ASP.NET MVC, Javascript, Node.js and Typescript.