🚨 ¡Nueva review! ¡Mi teclado ideal! ⌨️ Perfecto para programar, el Logitech MX Keys S . ¡Échale un ojo! 👀

¿Qué es el principio de responsabilidad única o Single Responsibility Principle (SRP)?

Una clase, una única responsabilidad.

Escrito por domin el 11 de agosto de 2024 · Actualizado el 14 de mayo de 2026

🧩 Single Responsibility Principle (SRP) - Principio de Responsabilidad Única

¿Qué es esto?

El Single Responsibility Principle es uno de los cinco principios SOLID de la programación orientada a objetos. Este principio dice que una clase debe tener una única responsabilidad y por lo tanto solo una razón para cambiar.

La frase original de Robert C. Martin, el tío Bob, que fue quien formuló este principio, es:

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

Gato negro representando el principio de responsabilidad única SRP de los principios SOLID.

¿Por qué es tan importante el SRP?

Aplicar el SRP lo hace todo más fácil:


Ejemplo

Imagina que trabajas en una tienda muy grande como un empleado que lo hace todo. Repones productos en las estanterías, atiendes a los clientes, cobras en la caja, revisas el stock, haces pedidos, cuadras las cuentas, contactas con distribuidores…

Es bastante probable que exista un empleado con todas estas tareas, quizá en tiendas pequeñas, pero en una tienda grande la tendencia es distribuir las tareas para ganar eficiencia y organización. Por ejemplo:

Repartir las tareas de esta forma también hace que las personas cometan menos fallos, porque se especializan en sus tareas y las hacen bien.

En la programación pasa algo parecido. Si tienes una clase que hace de todo, al final si hay algo mal en esa clase puede hacer petar toda la aplicación.

Si algo va mal o hay que cambiar algo, todo el sistema se ve sensible a fallos. Corregir un pequeño problema puede generar varios más y acabar siendo bastante costoso.

Por eso tu clase SuperEmpleado no debería implementar los métodos Atender, Reponer, Cobrar, CuadrarCuentas, RevisarStock… quedaría algo así:

class SuperEmpleado {
    public function atenderCliente() { /* ... */ }
    public function reponerProductos() { /* ... */ }
    public function cobrar() { /* ... */ }
    public function revisarStock() { /* ... */ }
    public function hacerPedidos() { /* ... */ }
    public function cuadrarCuentas() { /* ... */ }
}

$empleadoEjemplar = new SuperEmpleado();

Esta clase tiene seis razones para cambiar. Si cambia la lógica de cobro, tocas esta clase. Si cambia el proceso de reposición, tocas la misma clase. Cualquier cambio en cualquier área afecta a la misma clase y eso al final puede ser una bomba.


Refactor

Si refactorizamos SuperEmpleado para cumplir el SRP quedaría algo así:

class Vendedor {
    public function atenderCliente() { /* ... */ }
}

class Reponedor {
    public function reponerProductos() { /* ... */ }
}

class Cajero {
    public function cobrar() { /* ... */ }
}

class GestorInventario {
    public function revisarStock() { /* ... */ }
    public function hacerPedidos() { /* ... */ }
}

class Contable {
    public function cuadrarCuentas() { /* ... */ }
}

Ahora cada clase tiene una sola razón para existir. Si mañana cambia la forma de cobrar, solo tocas Cajero. Si cambia la lógica de inventario, solo tocas GestorInventario. El resto del sistema permanece intacto.

Con este refactor ganamos:


Otro ejemplo: la clase User

El ejemplo de la tienda es muy visual, pero vamos a ver uno que se replica en muchas plataformas. Imagina una clase User típica:

class User {
    public function getName(): string { /* ... */ }
    public function getEmail(): string { /* ... */ }

    // Persistencia
    public function save(): void { /* guarda en base de datos */ }

    // Notificaciones
    public function sendWelcomeEmail(): void { /* envía un email */ }

    // Validación
    public function validate(): bool { /* valida los datos */ }

    // Formateo
    public function toJson(): string { /* convierte a JSON */ }
}

Esta clase tiene cuatro responsabilidades mezcladas: datos del usuario, persistencia, notificaciones y serialización. Así que podemos decir que tiene 4 razones para cambiar.

El refactor sería:

class User {
    public function __construct(
        private string $name,
        private string $email,
    ) {}

    public function getName(): string { return $this->name; }
    public function getEmail(): string { return $this->email; }
}

class UserRepository {
    public function save(User $user): void { /* guarda en base de datos */ }
}

class UserNotifier {
    public function sendWelcomeEmail(User $user): void { /* envía email */ }
}

class UserValidator {
    public function validate(User $user): bool { /* valida datos */ }
}

class UserSerializer {
    public function toJson(User $user): string { /* convierte a JSON */ }
}

Ahora User solo se encarga de sus datos y la persistencia, las notificaciones, la validación y el formateo están cada uno en su sitio.


¿Cómo detectar que estás violando el SRP?

Hay varias pistas que te avisan de que una clase está haciendo demasiado y por lo tanto, incumpliendo el SRP:


Errores comunes al aplicar el SRP

Ojo, que aplicar el SRP también tiene sus trampas:


Conclusión

El SRP es probablemente el principio SOLID más fácil de entender pero uno de los más difíciles de aplicar bien en la práctica. Hay que preguntarse siempre: “¿Cuántas razones tiene esta clase para cambiar?”. Si la respuesta es más de una toca trabajar y refactorizar.

El objetivo del SRP es que cada clase tenga una responsabilidad clara y bien definida, de forma que cuando algo cambie, sepas exactamente dónde ir a tocarlo sin miedo a romper nada más.

Espero que se haya entendido ejeejjeje EA nos beermos! 🍻


Pon a prueba lo aprendido

1. ¿Qué dice exactamente el Principio de Responsabilidad Única?

2. En el ejemplo de la tienda, ¿por qué la clase SuperEmpleado viola el SRP?

3. ¿Cuál de estas señales NO indica una violación del SRP?