Single-Responsibility Principle – Java

In this article, we will be focusing on the Single-Responsibility Principle (SRP). SRP is the S in the SOLID principles, which are a set of software design principles. In the context of object-oriented programming and software development, these are intended to make software more understandable, flexible, and maintainable.

The acronym SOLID stands for:

  • SRP: Single-Responsibility Principle
  • OCP: Open/Closed Principle
  • LSP: Liskov Substitution Principle
  • ISP: Interface Segregation Principle
  • DIP: Dependency-Inversion Principle

The Single-Responsibility Principle (SRP)

SRP states:

A class should have only one reason to change.

Another way to interrupt this is:

A class should do one thing, and one thing only.

Or:

A class should only have one job or responsibility.

The purpose behind the SRP is to make the software easier to maintain and understand. When a class has only one responsibility, it will have fewer test cases and is less likely to be affected by changes in other parts of the software. This reduces the risk of introducing bugs when the class or its functionality needs to be modified.

In contrast, if a class has multiple responsibilities, a change in one of its responsibilities may inadvertently affect its other responsibilities. This can make bugs harder to track down and may make the class more difficult to understand, and maintain.

SRP Violation

Let’s look at the following code example of a User class.

public class User {
    private String name;
    private String email;
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
    public boolean isValidUser() {
        if (this.name == null || this.email == null) {
            return false;
        }
        return email.contains("@");
    }
    public void saveUser() {
        System.out.println("User saved to database");
    }
}

In the above code, the User class has two responsibilities:

  1. It validates the user information.
  2. It saves the user data to the database.

This class is clearly doing two different things. Therefore, this class would have two reasons to change. But, what do I mean by change?

Reason To Change

In the context of software design, a “reason to change” is a change to the business requirements that would require a modification of your source code. For example:

  1. If the way we validate a user changes, we would have to modify the isValidUser() method in the User class.
  2. If the way we save a user to the database changes, we would need to modify the saveUser() method in the User class.

Defining a Responsibility

In the context of the SRP, we define a responsibility to be a reason for change. If you can think of more than one reason to change a class, then that class has more than on responsibility.

Let’s look at another code example.

public class Order {
    private List<Item> items;
    public Order(List<Item> items) {
        this.items = items;
    }
    public double calculateTotal() {
        double total = 0;
        for (Item item : items) {
            total += item.getPrice();
        }
        return total;
    }
    public void printInvoice() {
        double total = calculateTotal();
        System.out.println("Order Invoice");
        System.out.println("Items: " + items);
        System.out.println("Total: " + total);
    }
}

Before reading on, can you tell if this class violates the SRP?

Yes, of course it does. The Order class is doing more than one thing. It is:

  1. Calculating the total cost of the order, and
  2. Printing the invoice.

How can we change this so that it does not violate SRP?

Code Refactor

To fix this violation, we should split these responsibilities into two classes.

  1. The Order class should only be responsible for holding order information and calculating the total.
  2. We can introduce a new InvoicePrinter class that is only responsible for printing invoices.

Here’s our new refactored code:

public class Order {
    private List<Item> items;
    public Order(List<Item> items) {
        this.items = items;
    }
    public double calculateTotal() {
        double total = 0;
        for (Item item : items) {
            total += item.getPrice();
        }
        return total;
    }
}
public class InvoicePrinter {
    public void printInvoice(Order order) {
        double total = order.calculateTotal();
        System.out.println("Order Invoice");
        System.out.println("Items: " + order.items);
        System.out.println("Total: " + total);
    }
}

Now, after the refactoring, each class only has one reason to change.

  1. If how we calculate the total changes, InvoicePrinter class will not be impacted.
  2. If how we print the invoice changes, then the Order class will not be impacted.

Of course, these examples are very simple, and maybe adding the complexity that comes with the SRP is just making your code base more complicated. But that is for you to decide when you’re writing your code.

Conclusion

The Single Responsibility Principle (SRP) is one of simplest of the SOLID principles but one of the most difficult to get right. It is a vital part of the principles, which are the cornerstone of object-oriented programming and software development.

The SRP emphasises that a class should have only one reason to change, effectively meaning it should have only one job or responsibility.

Applying the SRP can significantly improve the maintainability and understandability of your software. It minimises the impact of changes in the software requirements, reduces the introduction of bugs, and makes the software easier to comprehend.

However, like any principle or guideline, SRP isn’t a one-size-fits-all solution. There are scenarios where applying the SRP might lead to unnecessary complexity. The key is to strike a balance and apply these principles wisely, considering the specific needs and context of your software project.

Remember, the goal is to create a software system that is easy to manage, understand, and change. The SOLID principles, including SRP, offer a pathway to achieve this goal.

Scroll to Top