Skip to content
APPCITORThe Tech Blog
Esc

Single Responsibility Principle (SRP) with 100% understandable examples

January 2, 2023 2 min read

SOLID srp compress

What is SRP?

The Single Responsibility Principle (SRP) is a principle of object-oriented design that states that a class should have only one reason to change. In other words, a class should have only one responsibility. This principle helps to make software more maintainable and easier to modify.

Here are a few real-world examples of the Single Responsibility Principle with example code blocks (Javascript)
class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class UserAccounts {
  constructor() {
    this.users = [];
  }

  addUser(user) {
    this.users.push(user);
  }

  getUsers() {
    return this.users;
  }
}

In this example, the User class has a single responsibility: to represent a user with a name. The UserAccounts class has a single responsibility: to manage a list of users. Each class has a clear and well-defined purpose, which makes the code easier to understand and maintain.


class Animal {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class AnimalTrackingSystem {
  constructor() {
    this.animals = [];
  }

  addAnimal(animal) {
    this.animals.push(animal);
  }

  removeAnimal(animal) {
    this.animals = this.animals.filter(a => a.getName() !== animal.getName());
  }

  getAnimalCount() {
    return this.animals.length;
  }
}

In this example, the Animal class has a single responsibility: to represent an animal with a name. The AnimalTrackingSystem class has a single responsibility: to manage a list of animals and provide methods for adding, removing, and counting them. This separation of responsibilities makes the code easier to understand and maintain.


class BankAccount {
  constructor(balance) {
    this.balance = balance;
  }

  deposit(amount) {
    this.balance += amount;
  }

  withdraw(amount) {
    if (this.balance >= amount) {
      this.balance -= amount;
      return amount;
    } else {
      return 'Insufficient funds';
    }
  }
}

class BankAccountHistory {
  constructor() {
    this.transactions = [];
  }

  addTransaction(transaction) {
    this.transactions.push(transaction);
  }

  getTransactions() {
    return this.transactions;
  }
}

class BankAccountController {
  constructor(bankAccount, bankAccountHistory) {
    this.bankAccount = bankAccount;
    this.bankAccountHistory = bankAccountHistory;
  }

  deposit(amount) {
    this.bankAccount.deposit(amount);
    this.bankAccountHistory.addTransaction({type: 'deposit', amount: amount});
  }

  withdraw(amount) {
    const result = this.bankAccount.withdraw(amount);
    if (result !== 'Insufficient funds') {
      this.bankAccountHistory.addTransaction({type: 'withdraw', amount: amount});
    }
    return result;
  }
}

In this example, the BankAccount class has a single responsibility: to represent a bank account and provide methods for depositing and withdrawing funds. The BankAccountHistory class has a single responsibility: to record and store a list of transactions. The BankAccountController class has a single responsibility: to act as a controller for the BankAccount and BankAccountHistory classes, providing a single point of entry for interacting with them.

By following the Single Responsibility Principle, the code is more modular and easier to understand. It’s also easier to test, since each class has a single, well-defined purpose.

On next article we can check what is Open-Closed Principle.

Share this article

Keep reading