Aplicar el principio de responsabilidad única (SRP) es el primer paso para dejar de escribir código que da vergüenza ajena. En este post te muestro cómo separando validación, guardado y notificación en PHP puro podés mejorar la mantenibilidad, testeo y claridad de tus clases sin necesidad de frameworks ni arquitectura compleja. SRP es simple, útil y te salva el futuro.
"Una clase debe tener una única razón para cambiar." — Robert C. Martin (Uncle Bob)
Hace años que laburo en proyectos grandes y chicos, desde sitios a medida hasta sistemas empresariales con miles de líneas de código. Y si hay un principio que siempre aplico primero cuando empiezo a ordenar código es este: Single Responsibility Principle, o SRP para los amigos.
La idea es simple: 👉 Cada clase (o función) debería encargarse de una sola cosa. Nada más. Nada menos.
No es magia, pero cuando lo aplicás bien, el código respira.
Alguna vez (o muchas) escribimos algo así:
class UserManager {
public function register(array $data): void {
// Validación
if (empty($data['email'])) {
throw new Exception("Falta el email");
}
// Guardado
$userFile = fopen('usuarios.txt', 'a');
fwrite($userFile, json_encode($data) . PHP_EOL);
fclose($userFile);
// Notificación
mail($data['email'], 'Bienvenido', 'Gracias por registrarte.');
}
}
Este UserManager
hace todo: valida, guarda y notifica. Parece práctico, pero es un caldo de cultivo para bugs y frustración. Si mañana cambia el formato de guardado, el mail, o las reglas de validación, esta clase va a explotar por todos lados.
La idea es separar responsabilidades. Cada clase o función se encarga de una sola cosa.
class UserValidator {
public function validate(array $data): void {
if (empty($data['email'])) {
throw new Exception("Falta el email");
}
}
}
class UserRepository {
public function save(array $data): void {
$file = fopen('usuarios.txt', 'a');
fwrite($file, json_encode($data) . PHP_EOL);
fclose($file);
}
}
class UserNotifier {
public function sendWelcomeEmail(string $email): void {
mail($email, 'Bienvenido', 'Gracias por registrarte.');
}
}
class UserRegistration {
public function __construct(
private UserValidator $validator,
private UserRepository $repository,
private UserNotifier $notifier
) {}
public function register(array $data): void {
$this->validator->validate($data);
$this->repository->save($data);
$this->notifier->sendWelcomeEmail($data['email']);
}
}
$registration = new UserRegistration(
new UserValidator(),
new UserRepository(),
new UserNotifier()
);
$registration->register([
'email' => 'usuario@ejemplo.com',
'nombre' => 'Juan'
]);
Cuando estás apurado o el cliente te aprieta, te tentás a meter todo junto. Pero después te pasa la factura: clases imposibles de testear, cambios que rompen todo, bugs que aparecen por magia negra.
Separar responsabilidades te permite testear, cambiar y escalar sin miedo.
Podés mockear UserNotifier
, testear UserValidator
de forma aislada, o guardar a otro medio (MySQL, Mongo, lo que sea) sin tocar el resto.
SRP no es sólo teoría. En mi experiencia, es el primer paso real para tener un código que no odies leer dentro de seis meses. No necesitás frameworks ni arquitectura hexagonal para aplicarlo: solo ganas de escribir mejor código.
Y si estás en un equipo, aplicar SRP facilita el trabajo en paralelo y baja el nivel de quilombos.
¿Vos también tenés una clase tipo MegaServiceGodClass
en tu código? Es hora de jubilarla.
SRP no es glamour, es supervivencia.
¿Te gustó el enfoque? ¿Querés que lo adapte con más humor, o más orientado a Laravel o Filament?
Me dedico a crear soluciones web eficientes y a compartir mi conocimiento con la comunidad de desarrolladores.