terminal

codeando_simple

terminal

menu

terminal

search_module

guest@codeandosimple: ~/system/search $ grep -r "" .

Press [ENTER] to execute search

Status

Engine: Ready

Database: Online

Index: V2.1.0_LATEST

bash -- cat single-responsibility.md
guest@codeandosimple: ~/blog/solid $ cat single-responsibility.md

SOLID - SINGLE RESPONSIBILITY PRINCIPLE_

// "A good software developer works with discipline and constancy from day one." - Omar Bradley

The Single Responsibility Principle (SRP) states that "a class should have one, and only one, reason to change".

play_circle

Play explanatory video

In simpler terms, each class or module should be responsible for a specific part of the functionality, and that responsibility should be entirely encapsulated by the class.

# Responsibility?

When we talk about responsibility, we are talking about roles, about stakeholders in a module or function, actors who require changes to the software. Responsibilities are basically families of functions that meet the needs of those actors.

When any of the roles involved in these responsibilities decide to change or add functionality, they will have to change that class. Increasing the probability of collision, complexity, and potential bugs.

In the following example, we have a class that affects several actors, several responsibilities:

class Employee {
    public function calculatePay() { // ... // Accounting }
    public function save() { // ... // IT }
    public function describeEmployee() { // ... // Human Resources }
    }

On one hand Accounting, on another IT, and on another HR. A change required by one of them will affect the others.

# Why is it important?

The disadvantage of a class or module having more than one responsibility—or better said, having more than one reason to change—is that when a change is introduced for one of the responsibilities, it can affect the functioning of others.

Maintainability

It is easier to maintain and modify the code.

Flexibility

You can change one part of the system without affecting others.

Understandability

Each part of the system can be understood in isolation.

# Symptoms of violation

We can identify when we are not respecting SRP:

  • Class with many lines of code.
  • Every time a change is made or functionality is added, it is necessary to touch many places.
  • Mixing functionalities from different architectural layers.
  • "Touching one part" causes "something else to break" in the same module or class.

Example

Suppose we have an application to manage products in a store.

Without Single Responsibility Principle:

A bad practice would be to have a class that handles both database operations and the business logic of products.

public class ProductManager {
    public void addProduct(Product product) {
        // Logic to add product to the database
    }
    public void calculateTotalStockValue() {
        // Logic to calculate total inventory value
    }
    }

// Here, ProductManager has multiple reasons to change, which violates SRP.

With Single Responsibility Principle:

We are going to separate the responsibilities into two distinct classes: one that handles the interaction with the database and another that handles the inventory calculations.

// ProductDB.java

public class ProductDB {
    public void addProduct(Product product) {
        // Handles only the database logic to add products
    }
    }

// InventoryCalculator.java

public class InventoryCalculator {
    public double calculateTotalStockValue() {
        // Handles only the logic to calculate the inventory value
        // Returns the calculated value
        return 0.0;
    }
    }

// Product.java (Entity)

public class Product {
    // Attributes like name, price, quantity, etc.
    private String name;
    private double price;
    private int quantity;
    // Constructor, getters and setters
    public Product(String name, double price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }
    // ... (other methods and attributes)
    }

Conclusions

By implementing SRP, ProductDB exclusively handles database interaction, while InventoryCalculator only handles inventory-related calculations.

This not only makes the code easier to maintain and extend but also helps avoid complicated errors that can arise when a class has too many responsibilities.

Summary

When we talk about a single responsibility, it doesn't mean that a class has only one method, nor a module that has only one class, but that it includes all the related functionality that can change together, that depends on the same actor.

A correct application of the Single Responsibility Principle makes our code flexible to change and less prone to errors.