DEV Community

Cover image for S.O.L.I.D: Single Responsibility Principle
Abhishek Prakash
Abhishek Prakash

Posted on • Updated on • Originally published at blog.abhishekprakash.com

S.O.L.I.D: Single Responsibility Principle

What is S.O.L.I.D by the way?

As per Wiki:

In object-oriented computer programming, SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible and maintainable.

SOLID is an acronym for 5 important design principles when doing OOP. It was first introduced by Robert C. Martin (Uncle Bob), in his 2000 paper Design Principles and Design Patterns.

SOLID stands for -

  • S - Single Responsibility Principle
  • O - Open/Closed Principle
  • L - Liskov's Substitution Principle
  • I - Interface Segregation Principle
  • D - Dependency Inversion Principle

In this article, I will be covering S - Single Responsibility Principle.
Note - The examples will be in Java, but applies to any OOP language.

S - Single Responsibility Principle (SRP)

A class should have one, and only one reason to change.

In programming, the Single Responsibility Principle states that every module or class should have responsibility for a single part of the functionality provided by the software.

Anti SRP Usage

An action example speaks louder than voice

package app.singleResponsibility;

public class Employee {
  private String name;
  private int perHourRate;

  public Employee(String name) {
    this.name = name;
  }

  public String getName() {
      return name;
  }

  public void setPerHourRate(int rate) {
    this.perHourRate = rate;
  }

  public int getPerDayRate() {
    return perHourRate * 8;
  }


  public String markAttendance() {
    return String.format("%s is present", name);
  }
}

And here goes the UML Diagram for the geeks -
UML diagram of Employee class

So we have a very basic Employee class with two private attributes and a few public methods. At first glance, it looks fine, but it's actually breaking SRP.

Employee class not only deals with Employee details but it is also concerned with the implementation of the markAttendence method. It has two reasons to change now.

SRP in Action

The previous example violates the SRP law of single responsibility. Let's dig a little further and try to correct the Employee class.


// Employee.java
package app.singleResponsibility;

public class Employee {
  private String name;
  private int perHourRate;

  public Employee(String name) {
    this.name = name;
  }

  public String getName() {
      return name;
  }

  public void setPerHourRate(int rate) {
    this.perHourRate = rate;
  }

  public int getPerDayRate() {
    return perHourRate * 8;
  }
}

The updated UML diagram for Employee class -
Alt Text

We have removed the markAttendance method from the Employee class to make it compliant with SRP.

Let's go further and create the AttendanceTracker class to deal with attendance.

// AttendanceTracker.java
package app.singleResponsibility;

public class AttendanceTracker {
  private Employee emp;

  public AttendanceTracker(Employee emp) {
    this.emp = emp;
  }

  public String markAttendance() {
    return String.format("%s is present", emp.getName());
  }
}

UML diagram for AttendanceTracker class
UML diagram for AttendanceTracker class

AttendanceTracker class takes an employee object as a dependency and marks the attendance of that employee.

Now both the classes adhere to the Single Responsibility Principle and it makes the maintenance and testing a breeze.

TL;DR

The more responsibilities (reason to change) a class has, it's going to get harder to implement some new features and the maintenance will be a growing pain that will burn more time as the project grows, adding more complexity and making the classes responsibilities strongly coupled to each other.

So, always have small classes with a single responsibility.

Peace!
If you have any questions or feedback, please feel free to comment below.

Top comments (3)

Collapse
 
tylerwbrown profile image
Tyler Brown

Hey, nice post! The SRP is definitely a super important principle to keep in mind while coding.

However, to change the context here, let me change some of this code to use a newer Java 14 feature (the version of Java that's going to release later this month).

Instead of:

package app.singleResponsibility;

public class Employee {
  private String name;
  private int perHourRate;

  public Employee(String name) {
    this.name = name;
  }

  public String getName() {
      return name;
  }

  public void setPerHourRate(int rate) {
    this.perHourRate = rate;
  }

  public int getPerDayRate() {
    return perHourRate * 8;
  }
}

we can do:

package app.singleResponsibility;

public record Employee(String name, int perHourRate) {
  public int perDayRate() { 
    return perHourRate * 8; 
  }
}

Getters are handled automatically by records and they follow slightly different conventions. Setters don't exist, you'd instead "mutate" a record by making a new one.

The point here is that following the SRP depends on context. In older languages/versions, what might be considered breaking the SRP might not be anymore. As we move to higher level languages, the semantics improve and we can be more expressive about the code we write, which means a "single responsibility" encapsulates more than it used to.

I'm not disagreeing with your post here, just adding additional context to the discussion :)

And again, well done on the post!

Collapse
 
linuxnerd profile image
Abhishek Prakash

I am glad you liked the post! Thanks for the insight and definitely newer version of Java will help to reduce the verbosity. But, I am still confused how the context will impact the SRP. Can you explain with an example?

Collapse
 
anshulkatta profile image
Anshul Katta

Nice article about Single Responsibility and code for class Employee is refactored ...

but i disagree with AttendanceTracker having has a relationship with Employee object...

and operation on employee object doesnt require another class but in fact there is a need of util or in functional paradigm we need functions to perform operation on employee object ...in my opinion