Skip to main content

Inicia sesión en CleanKata

Sigue tu progreso, gana XP y desbloquea todas las lecciones.

Al iniciar sesión aceptas nuestros Términos de uso y Política de privacidad.

Arquitectura Limpia70 XP7 min

SRP: El Principio de Responsabilidad Única

Un módulo debe ser responsable ante un solo actor, evitando que los cambios de un departamento rompan accidentalmente otro.

Por qué importa

El SRP se malinterpreta comúnmente como "un módulo debe hacer solo una cosa". La definición real, como aclara Robert Martin en Clean Architecture, es más precisa: un módulo debe ser responsable ante uno, y solo uno, actor. Un actor es un grupo de personas — un departamento, un rol — cuyas exigencias impulsan cambios en ese módulo.

El ejemplo canónico es una clase Employee con tres métodos: calculatePay() solicitado por el CFO, reportHours() solicitado por el COO, y save() solicitado por el CTO. Cuando estos tres métodos comparten un helper privado — digamos, _regularHours() — el equipo del CFO puede romper accidentalmente los informes del COO simplemente ajustando el algoritmo de cálculo de pago. Los dos actores ahora están acoplados involuntariamente a través de una clase compartida. La cohesión es la fuerza que mantiene juntas las cosas que cambian por la misma razón; el SRP es el principio que separa las cosas que cambian por razones diferentes.

✗El problema

Three actors — CFO, COO, CTO — all depend on one class. A change requested by one actor silently breaks the logic used by another.

Bad

class Employee:
    def calculate_pay(self) -> float:   # owned by CFO
        hours = self._regular_hours()
        return hours * self.hourly_rate

    def report_hours(self) -> float:    # owned by COO
        hours = self._regular_hours()   # reuses same helper — coupling!
        return hours

    def save(self) -> None:             # owned by CTO / DBA
        db.save(self)

    def _regular_hours(self) -> float:  # shared — dangerous
        return self.total_hours - self.overtime_hours
class Employee {
  calculatePay(): number {          // CFO's concern
    return this.regularHours() * this.hourlyRate;
  }

  reportHours(): number {           // COO's concern
    return this.regularHours();     // accidental coupling!
  }

  save(): void {                    // CTO's concern
    db.save(this);
  }

  private regularHours(): number {  // shared — fragile
    return this.totalHours - this.overtimeHours;
  }
}

✓La solución

Three separate classes, one actor each. The Employee data structure holds state only — it has no behavior. Each class owns its own helper logic.

Good

class Employee:
    """Data structure only — no behavior."""
    total_hours: float
    overtime_hours: float
    hourly_rate: float

class PayCalculator:          # answers to CFO
    def calculate_pay(self, emp: Employee) -> float:
        return self._regular_hours(emp) * emp.hourly_rate

    def _regular_hours(self, emp: Employee) -> float:
        return emp.total_hours - emp.overtime_hours

class HourReporter:           # answers to COO
    def report_hours(self, emp: Employee) -> float:
        return emp.total_hours  # uses its own definition

class EmployeeRepository:     # answers to CTO / DBA
    def save(self, emp: Employee) -> None:
        db.save(emp)
interface Employee {
  totalHours: number;
  overtimeHours: number;
  hourlyRate: number;
}

class PayCalculator {                        // answers to CFO
  calculatePay(emp: Employee): number {
    return this.regularHours(emp) * emp.hourlyRate;
  }
  private regularHours(emp: Employee): number {
    return emp.totalHours - emp.overtimeHours;
  }
}

class HourReporter {                         // answers to COO
  reportHours(emp: Employee): number {
    return emp.totalHours;  // owns its own definition
  }
}

class EmployeeRepository {                   // answers to CTO
  save(emp: Employee): void {
    db.save(emp);
  }
}

💡Conclusión clave

El SRP no se trata de hacer una sola cosa — se trata de servir a un solo actor. Si dos ejecutivos diferentes pueden solicitar cambios conflictivos al mismo módulo, ese módulo está violando el SRP y es una bomba de tiempo para el acoplamiento accidental.

🔧 Algunos ejercicios pueden tener errores. Si algo parece incorrecto, usa el botón Feedback (abajo a la derecha) para reportarlo — nos ayuda a corregirlo rápido.

Pista: Si distintos ejecutivos pueden solicitar cambios conflictivos en la misma clase, sirve a múltiples actores — sepárala.

✗ Tu versión