Single Responsibilty Principle

Understanding the SOLID Principles: The Single Responsibility Principle (SRP)

Shahmir Khan
4 min readMar 5, 2025

When it comes to writing clean, maintainable, and scalable code, the SOLID principles are a set of guidelines that every developer should be familiar with. SOLID is an acronym that stands for five key principles of Object-Oriented Programming (OOP):

  1. Single Responsibility Principle (SRP)
  2. Open/Closed Principle (OCP)
  3. Liskov Substitution Principle (LSP)
  4. Interface Segregation Principle (ISP)
  5. Dependency Inversion Principle (DIP)

In this blog post, we’ll dive into the first principle: the Single Responsibility Principle (SRP). We’ll explore what it means, why it’s important, and how to apply it in your code with practical examples.

What is the Single Responsibility Principle (SRP)?

The Single Responsibility Principle states that:

A class should have only one reason to change, meaning it should have only one job or responsibility.

In other words, a class should be focused on doing one thing and doing it well. If a class has multiple responsibilities, it becomes harder to maintain, test, and understand. By adhering to SRP, you ensure that your classes are modular, easier to debug, and more reusable.

Why is SRP Important?

  1. Maintainability: When a class has only one responsibility, it’s easier to make changes without affecting other parts of the codebase.
  2. Testability: Smaller, focused classes are easier to test because they have fewer dependencies and edge cases.
  3. Reusability: Classes with a single responsibility can often be reused in different parts of the application or even in other projects.
  4. Readability: Code that follows SRP is easier to read and understand because each class has a clear and specific purpose.

Applying SRP in Code: Examples

Let’s look at two examples to understand how SRP can be applied in practice.

Example 1: User Class with JSON Serialization

Before Applying SRP

Here’s a simple User class that stores a user’s name and has a method to convert the user object to JSON:

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

toJSON() {
return JSON.stringify(this);
}
}

At first glance, this seems reasonable. However, this class violates SRP because it has two responsibilities:

  1. Modeling user data (storing the name).
  2. Serializing the user object to JSON.

If the JSON serialization logic changes (e.g., you want to add or exclude certain fields), you’ll need to modify the User class, which isn’t ideal.

After Applying SRP

To adhere to SRP, we can split the responsibilities into two separate classes:

// User class is only responsible for modeling user data
class User {
constructor(name) {
this.name = name;
}
}

// UserSerializer class is responsible for serializing user data
class UserSerializer {
static toJSON(user) {
return JSON.stringify(user);
}
}

Now, the User class is solely responsible for representing a user, and the UserSerializer class handles the serialization logic. This separation makes the code more modular and easier to maintain.

Example 2: User Class with Authentication and Database Saving

Before Applying SRP

Consider a User class that handles both authentication and saving the user to a database:

class User {
constructor(username, password) {
this.username = username;
this.password = password;
}

// Handles user authentication
authenticate(inputPassword) {
// Imagine a more secure hashing and matching process here
return this.password === inputPassword;
}

// Saves user to database
save() {
// Assume we have a connection to a db and a method to save a user
db.saveUser(this);
}
}

const user = new User('Maurice', 'secret');
if (user.authenticate('secret')) {
user.save();
}

This class has two responsibilities:

  1. Managing user attributes and authentication.
  2. Handling database operations.

If the database logic changes (e.g., switching from SQL to NoSQL), you’ll need to modify the User class, which violates SRP.

After Applying SRP

To adhere to SRP, we can separate the database logic into a new class called UserDataManager:

// User class is only responsible for user attributes and authentication
class User {
constructor(username, password) {
this.username = username;
this.password = password;
}

// Handles user authentication
authenticate(inputPassword) {
// Imagine a more secure hashing and matching process here
return this.password === inputPassword;
}
}

// UserDataManager class is responsible for database operations
class UserDataManager {
static save(user) {
// Assume this function gives a database connection
const db = getDatabaseConnection();
db.saveUser(user);
}
}

const user = new User('Alice', 'password123');
if (user.authenticate('password123')) {
UserDataManager.save(user);
}

Now, the User class is only concerned with user attributes and authentication, while the UserDataManager class handles database operations. Each class has a single responsibility, making the code easier to maintain and extend.

When Should You Apply SRP?

While SRP is a powerful principle, it’s important to use it judiciously. Over-engineering your code by creating too many small classes can lead to unnecessary complexity. SRP is most beneficial in larger applications where classes tend to grow and accumulate multiple responsibilities over time.

Conclusion

The Single Responsibility Principle (SRP) is the foundation of the SOLID principles. By ensuring that each class has only one responsibility, you can create code that is more modular, maintainable, and scalable. While the examples in this post are simple, the real power of SRP becomes evident in larger, more complex applications.

In the next blog post, we’ll explore the Open/Closed Principle (OCP), the second principle in the SOLID acronym. Stay tuned!

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Shahmir Khan
Shahmir Khan

Written by Shahmir Khan

Shahmir Khan have 5+ years of software development experience. He knows Javascript, PHP, ReactJS, NodeJS, VueJS and Laravel.

No responses yet

Write a response