La 'S' de SOLID: Principio de Responsabilidad Única (SRP) en C#


El Principio de Responsabilidad Única (Single Responsibility Principle o SRP) es la primera letra del acrónimo SOLID. Su definición es simple:

Una clase debe tener una, y solo una, razón para cambiar.

Dicho de otra forma, una clase debería encargarse de una única responsabilidad dentro del sistema. Veamos un ejemplo sencillo en C#.

El problema: Demasiadas responsabilidades

Supongamos que tenemos una clase Empleado que almacena información del empleado, calcula un bonus extra a partir de su sueldo y además se encarga de guardarlo en la base de datos.

public class Empleado
{
public string Nombre { get; set; }
public decimal Salario { get; set; }

```
// Responsabilidad 1: Lógica de negocio
public decimal CalcularBonus()
{
    return Salario * 0.10m;
}

// Responsabilidad 2: Persistencia
public void GuardarEnBaseDeDatos()
{
    Console.WriteLine("Empleado guardado en la base de datos.");
}
```

}

A primera vista parece práctico tener todo junto, pero esta clase tiene más de una responsabilidad.

Por un lado, conoce las reglas para calcular el bonus de un empleado. Por otro, sabe cómo almacenar la información en una base de datos.

¿Qué ocurriría si cambia alguna de estas cuestiones?

En ambos casos deberíamos modificar la misma clase.

Posibles razones para el cambio con el esquema actual

Cambio Clase afectada
Cambian las reglas de cálculo del bonus Empleado
Cambia la forma de persistir los datos Empleado

Esto viola el SRP porque la clase tiene más de una razón para cambiar.

La solución: Aplicando el SRP

La idea es separar cada responsabilidad en una clase distinta.

public class Empleado
{
    public string Nombre { get; set; }
    public decimal Salario { get; set; }
}
public class CalculadorBonus
{
    public decimal Calcular(Empleado empleado)
    {
        return empleado.Salario * 0.10m;
    }
}
public class RepositorioEmpleado
{
    public void Guardar(Empleado empleado)
    {
        Console.WriteLine("Empleado guardado en la base de datos.");
    }
}

Ahora cada clase tiene una responsabilidad bien definida:

Uso final

Empleado empleado = new Empleado
{
Nombre = "Ana",
Salario = 100000
};

CalculadorBonus calculador = new CalculadorBonus();
decimal bonus = calculador.Calcular(empleado);

RepositorioEmpleado repositorio = new RepositorioEmpleado();
repositorio.Guardar(empleado);

Console.WriteLine($"Bonus: {bonus}");

Posibles razones para el cambio con el nuevo diseño

Cambio Clase afectada
Cambian las reglas de cálculo del bonus CalculadorBonus
Cambia la forma de persistir los datos RepositorioEmpleado
Cambian los datos del empleado Empleado

Cada clase tiene ahora un único motivo para cambiar, cumpliendo así con el Principio de Responsabilidad Única.

Nota al pie: determinar qué constituye exactamente una “responsabilidad” no siempre es sencillo. A medida que ganes experiencia diseñando software, comenzarás a identificar con mayor facilidad cuándo una clase está asumiendo tareas que deberían estar separadas.