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_

// "Un buen desarrollador de software trabaja con disciplina y constancia desde el primer día." - Omar Bradley

El Single Responsibility Principle (SRP) o Principio de Responsabilidad Única estable que "una clase debe tener una, y solo una, razón para cambiar".

play_circle

Reproducir video explicativo

En términos más simples, cada clase o módulo debería ser responsable de una parte específica de la funcionalidad, y esa responsabilidad debería estar completamente encapsulada por la clase.

# ¿Responsabilidad?

Al hablar de responsabilidad, hablamos de roles, de interesados en un módulo o función, actores que requieren cambios al software. Las responsabilidades son básicamente familias de funciones que cumplen las necesidades de dichos actores.

Cuando alguno de los roles involucrados en dichas responsabilidades decida cambiar o agregar funcionalidad, va a tener que cambiar dicha clase. Aumentando la probabilidad de colisión, complejidad y posibles bugs.

En el siguiente ejemplo tenemos una clase que afecta a varios actores, varias responsabilidades:

class Employee {
    public function calculatePay() { // ... // Contabilidad }
    public function save() { // ... // IT }
    public function describeEmployee() { // ... // Recursos Humanos }
}

Por un lado contabilidad, por otro IT y por otro RRHH. Un cambio requerido por uno de ellos, va a afectar a los otros.

# ¿Por qué es importante?

La desventaja de que una clase o módulo tenga más de una responsabilidad, o mejor dicho, que tenga más de una razón para cambiar, es que cuando se introduce un cambio para alguna de las responsabilidades, puede afectar el funcionamiento de otras.

Mantenibilidad

Es más fácil mantener y modificar el código.

Flexibilidad

Puedes cambiar una parte del sistema sin afectar a otras.

Comprensibilidad

Cada parte del sistema se puede entender de manera aislada.

# Síntomas de que no se cumple

Podemos identificar cuándo no estamos respetando el SRP:

  • Clase con muchas líneas de código.
  • Cada vez que hay que se hace un cambio o se agrega una funcionalidad, es necesario tocar en muchos lugares.
  • Mezcla de funcionalidades de distintas capas de arquitectura.
  • "Tocar una parte" y que se "rompa otra cosa" del mismo módulo o clase.

Ejemplo

Supongamos que tenemos una aplicación para gestionar productos en una tienda.

Sin Single Responsibility Principle:

Una mala práctica sería tener una clase que maneje tanto las operaciones de la base de datos como la lógica de negocio de los productos.

public class ProductManager {
    public void addProduct(Product product) {
        // Lógica para agregar producto a la base de datos
    }
    public void calculateTotalStockValue() {
        // Lógica para calcular el valor total del inventario
    }
}

// Aquí, ProductManager tiene múltiples razones para cambiar, lo que incumple el SRP.

Con Single Responsibility Principle:

Vamos a separar las responsabilidades en dos clases distintas: una que maneje la interacción con la base de datos y otra que maneje los cálculos del inventario.

// ProductDB.java

public class ProductDB {
    public void addProduct(Product product) {
        // Solo maneja la lógica de la base de datos para agregar productos
    }
}

// InventoryCalculator.java

public class InventoryCalculator {
    public double calculateTotalStockValue() {
        // Solo maneja la lógica para calcular el valor del inventario
        // Retorna el valor calculado
        return 0.0;
    }
}

// Product.java (Entidad)

public class Product {
    // Atributos como nombre, precio, cantidad, etc.
    private String name;
    private double price;
    private int quantity;
    // Constructor, getters y setters
    public Product(String name, double price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }
    // ... (otros métodos y atributos)
}

Conclusiones

Al implementar el SRP, ProductDB se ocupa exclusivamente de la interacción con la base de datos, mientras que InventoryCalculator maneja solo los cálculos relacionados con el inventario.

Esto no solo hace que el código sea más fácil de mantener y extender, sino que también ayuda a evitar errores complicados que pueden surgir cuando una clase tiene demasiadas responsabilidades.

Resumen

Cuando se habla de una sola responsabilidad, no quiere decir que una clase tenga un sólo método, ni un módulo que tenga una sola clase, sino que incluya toda la funcionalidad relacionada que pueda cambiar junta, que dependa de un mismo actor.

Una correcta aplicación del principio de responsabilidad única hace que nuestro código sea flexible al cambio y lo vuelve menos propenso a errores.