DEV Community

Cover image for Single Responsibility Principle using TypeScript
Kinanee Samson
Kinanee Samson

Posted on

Single Responsibility Principle using TypeScript

This is one of the SOLID design principles and it is the first letter in the accronym. Single Responsibilty principle is concerned with ensuring that our modules, classes, methods can only do one thing and that they should only ever have one reason to change in the future and nothing more. In this series we are going to explore two different scenarios where this principle was not adhered to and how we can improve the code so it conforms to this Single Responsibility Principle.

To read more articles like this visit Netcreed

class Book {

  constructor(
    public pages: number, 
    public author: string, 
    public content: string
  ) {}

  updateAuthor(author: string) {
    this.author = author;
  }

  updateContent(content: string) {
    this.content = content;
  }

}
Enter fullscreen mode Exit fullscreen mode

Consider the class declared above, for starters it seems like everything is okay. However this class is not adhering to the single Responsibility principle, there is no clear distinction as to what the sole responsibility of this class is, the class has more than one reason to change; we could change the implementation of the getting the author or we could change the implementation of updating the book's content, we could also change the structure of the Book by adding or removing more properties, you start to see where this is going? so how do we fix that? We need to define a distinction between the Book as a data transfer object and functions that are responsible updating properties of the book.

export interface Book {
  pages: number;
  author: string;
  content: string
}

class TextBook {

  constructor(
    public pages: number, 
    public author: string, 
    public content: string
  ) {}

}

export const updateContent = (book: Book, content: string) => {
  book.content = content;
  return book;
}

export const updateAuthor = (book: Book, author: string) => {
  book.author = author;
  return book;
}
Enter fullscreen mode Exit fullscreen mode

Now we have refactored the class to conform to the single responsibility principle, the class is only responsible for storing a book object while we now have two helper functions, one for updating the content of the book, the other for updating the author of the book.

Let's see another example where this law is violated and how we can refactor the code to adhere to the law. Say we have a Person class that stores a reference to a user object, we now define two methods on the class one for greeting other users, and another for adding hobbies to the user's list of hobbies.

class Person {

  hoobies: string[] = []
  constructor(public name: string, public age: number){}

  sayHello(){
    console.log(`${this.name} says Hello!`)
  }

  addHobbies(hobby: string) {
    this.hoobies.push(hobby);
  }
}
Enter fullscreen mode Exit fullscreen mode

Like the first instance we used, this class is not adhering to the single responsibility principle. Again there is no clear distinction between the class that represents a user object and the methods that allow us to make some changes to the user object. What we can do to correct this is to extract and place the methods for greeting and for adding hobbies into helper functions, then the class is only responsible for storing a user object.

export interface User {
  name: string
  age: number
  hobbies: string[]
}

class Admin {
  hobbies: string[] = []
  constructor(
    public name: string,
    public age: number
  ) {}
}


export const sayHello = (name: string) => {
  console.log(`${name} says Hello!`)
}

export const addHobby = (user: User, hobby: string) => {
  user.hobbies.push(hobby);
}
Enter fullscreen mode Exit fullscreen mode

That's how we can refactor our classes to adhere to the single responsibility principle, rememeber this rule states that the each part of your program should only be responsible for one thing, be it a module, a class, a function thus, they should only ever have on reason to change.

To read more articles like this visit Netcreed

Top comments (0)