5.1Patrones de diseño, arquitectura limpia y SOLID
Lo esencial en 30 segundos
- Patrones = soluciones probadas: recetas de organización validadas (Factory, Repository, inyección de dependencias) + un vocabulario común.
- SOLID = 5 principios: responsabilidad única, abierto/cerrado, Liskov, segregación de interfaces, inversión de dependencias.
- Criterio: aplicar con medida según el problema — ni sobreingeniería, ni desorden.
Mini-caso hilado — Riad estructura su tienda en Constantina
Riad, desarrollador web en Constantina, mantiene una pequeña tienda en línea: el código mezcla consultas SQL, HTML y reglas de precios en los mismos archivos, y cada corrección rompe otra cosa. Centraliza el acceso a los datos en un Repository, inyecta sus dependencias en lugar de crearlas en duro, y divide una clase que lo hacía todo. Esta sección cuenta su cambio hacia un código diseñado para durar — y el hilo continúa en 5.2, 5.3 y 5.4.
Este mismo caso vuelve en el curso, el esquema, el guion y el reto 48h — y continúa en 5.2, 5.3 y 5.4.
1. Los patrones de diseño
En el nivel experto, la pregunta pasa a ser «cómo estructurar el código para que sea robusto, mantenible, evolutivo». Los patrones de diseño (design patterns) son soluciones probadas a problemas de diseño recurrentes: recetas de organización validadas por la comunidad, que evitan reinventar la rueda. Habituales en PHP: la Factory (delegar la creación de objetos para desacoplar), el Repository (centralizar el acceso a los datos de una entidad), la Strategy (algoritmos intercambiables), el Observer (notificar un evento), la inyección de dependencias (aportar a un objeto sus dependencias desde fuera — central en los frameworks modernos). Riad reencuentra en ellos sus problemas diarios ya resueltos por otros.
Ventaja decisiva: los patrones dan un vocabulario común — decir «es un Repository» comunica una intención de diseño. Y los frameworks (Laravel, Symfony) los usan masivamente: reconocerlos es comprender lo que hace el framework en lugar de sufrirlo.
2. Los principios SOLID
SOLID son cinco principios de diseño orientado a objetos: Single Responsibility (una clase = una sola responsabilidad, una sola razón para cambiar), Open/Closed (abierto a la extensión, cerrado a la modificación: añadir sin romper lo existente), Liskov Substitution (una clase derivada debe poder sustituir a su madre sin romper el comportamiento), Interface Segregation (varias interfaces específicas en lugar de una gran interfaz general), Dependency Inversion (depender de abstracciones — interfaces — en lugar de implementaciones concretas). Aplicados, producen un código desacoplado, extensible, testeable. Riad empieza por la S y la D: divide su clase cajón de sastre, luego depende de una interfaz.
La arquitectura limpia prolonga esta reflexión: separación de capas, desacoplamiento, código legible. Un código que respeta estos principios se prueba fácilmente — y se evoluciona sin miedo.
3. El criterio ante todo
Punto de perspectiva esencial: patrones y SOLID se aplican con criterio, no dogmáticamente. La sobreingeniería (patrones complejos y capas de abstracción donde bastaría una solución simple) es una trampa tan real como la infraingeniería (código desordenado): complejidad inútil, código más difícil de comprender, rigidez paradójica, tiempo perdido. Riad no añade tres capas a un script de una página — estructura lo que crece y dura.
Estos conceptos son además transversales: valen en toda programación orientada a objetos, más allá de PHP. Dominarlos marca el paso hacia la experiencia: ya no basta con hacer funcionar el código, se diseña para que dure — una competencia que se adquiere con la práctica y la lectura de buen código, en particular el de los frameworks.
🔎 Ejemplo concreto — Riad centraliza el acceso a los datos
Un Repository testeable, dependencia inyectada.
pdo->prepare('SELECT * FROM produits WHERE id = :id');
$req->execute(['id' => $id]);
$ligne = $req->fetch(PDO::FETCH_ASSOC);
return $ligne === false ? null : $ligne;
}
}
// El controlador recibe el depósito (inyección), no lo crea :
// $controleur = new ProduitControleur(new ProduitRepository($pdo));
Lectura: el SQL vive en el mismo lugar, el controlador depende de una interfaz — se puede probar con un depósito falso.
Lección: Repository + inyección = código desacoplado, testeable, que evoluciona sin roturas.
Vocabulario de la sección
- Patrones de diseño
- Soluciones probadas a problemas de diseño recurrentes, con un vocabulario común.
Ejemplo sencillo: Riad centraliza sus consultas de productos en un Repository.
Lo que no es: unas reglas obligatorias a aplicar en todas partes.
Reflejo: ¿qué problema recurrente estoy resolviendo?
- Repository
- Patrón que centraliza el acceso a los datos de una entidad en un solo lugar.
Ejemplo sencillo: Todas las consultas de productos de Riad pasan por ProduitRepository.
Lo que no es: SQL esparcido en las vistas y los controladores.
Reflejo: ¿mi SQL está agrupado y es reutilizable?
- Inyección de dependencias
- Aportar a un objeto sus dependencias desde fuera en lugar de que las cree.
Ejemplo sencillo: El controlador de Riad recibe el PDO en lugar de construirlo.
Lo que no es: un new PDO oculto al fondo de un método.
Reflejo: ¿puedo probar esta clase con un falso?
- SOLID
- Cinco principios de diseño OO hacia un código desacoplado y mantenible.
Ejemplo sencillo: Riad divide su clase cajón de sastre (S) y luego depende de interfaces (D).
Lo que no es: una lista de control a marcar ciegamente.
Reflejo: ¿qué letra SOLID alivia mi dolor actual?
- Sobreingeniería
- Demasiada estructura y abstracciones donde bastaría una solución simple.
Ejemplo sencillo: Riad deja simple su script de una página, sin capas.
Lo que no es: el código desordenado sin ninguna estructura.
Reflejo: ¿esta abstracción paga su coste?
En la práctica — Diseñar un código limpio y mantenible
- Descubra algunos patrones de diseño habituales (Factory, Repository, inyección de dependencias) y detéctelos en el código de un framework (Laravel/Symfony).
- Aplique la Responsabilidad única (S de SOLID): una clase = una responsabilidad; divida una clase que haga demasiado.
- Aplique la Inversión de dependencias (D): haga depender su código de una INTERFAZ en lugar de una clase concreta (más flexible, testeable).
- Ejercite el CRITERIO: aplique la estructura adaptada al problema, sin sobreingeniería (ni patrones complejos inútiles, ni desorden).
Guion listo para decir — proponer un despiece limpio
«En nuestra tienda en Constantina, las consultas SQL están mezcladas con el HTML y cada corrección rompe otra cosa. Propongo centralizar el acceso a los datos en un Repository e inyectar las dependencias: podremos probar sin la base y modificar la visualización sin tocar los datos. Empiezo por una clase, medimos la ganancia, luego ampliamos.»
A decir en revisión de código para hacer adoptar un despiece progresivo, sin prometer una reescritura completa.
Modelo copiar-pegar — parrilla de relectura SOLID
RELECTURA SOLID (1 clase)
S — Responsabilidad única : ¿esta clase tiene UNA sola razón para cambiar? → Si no : ¿qué dividir? ___
O — Abierto/Cerrado : para añadir un caso, ¿debo MODIFICAR lo existente? → Si sí : ¿qué extensión prever? ___
L — Liskov : ¿una clase hija puede sustituir a su madre? → Test : ___
I — Interfaces : ¿la interfaz es demasiado grande? → A dividir en : ___
D — Inversión : ¿de qué CONCRETO depende? → Sustituir por la interfaz : ___
Solo / presupuesto pequeño
Riad solo: aplicar S y D en las dos clases más dolorosas basta — no hace falta reestructurarlo todo.
TPE / equipo reducido
Un Repository compartido para las entidades críticas: todo el equipo lee y escribe los datos en el mismo lugar.
PYME en Constantina
Riad fija una relectura SOLID mensual con el equipo en Constantina: una clase pasada por la parrilla cada vez.
Equipo que empieza
Pareja: uno codifica la funcionalidad, el otro relee con la parrilla; solo se añade un patrón ante un problema real.
✓ Buenas prácticas
- Empezar por S (responsabilidad única) y D (inversión de dependencias): la mejor relación esfuerzo/ganancia.
- Leer buen código (frameworks) para ver los patrones en situación real.
- Solo añadir un patrón ante un problema real de mantenimiento o de test.
✗ Errores frecuentes
- Aplicar patrones en todas partes «para ser pro» (sobreingeniería).
- Abusar del Singleton (estado global oculto, tests difíciles) — a usar con parsimonia.
- Confundir arquitectura y papeleo: unas capas que no aportan nada cuestan en comprensión.
Puntos clave
- PATRONES DE DISEÑO = soluciones PROBADAS a problemas de diseño recurrentes (Factory, Repository, Strategy, Observer, inyección de dependencias); vocabulario común. Los frameworks los usan masivamente.
- SOLID = 5 principios de diseño OO: Single Responsibility (una responsabilidad), Open/Closed (extensión sin modificación), Liskov, Interface Segregation, Dependency Inversion (depender de ABSTRACCIONES).
- Aplicados, producen un código DESACOPLADO, extensible, testeable, mantenible (arquitectura limpia: capas separadas, desacoplamiento, legibilidad).
- CRITERIO: aplicar con MEDIDA según el problema — la SOBREINGENIERÍA (estructura excesiva) es una trampa como el desorden. Conceptos TRANSVERSALES (más allá de PHP). Marca el paso hacia la EXPERIENCIA (diseñar, no solo hacer funcionar).
Reto 48h — aplique mañana
Pase 1 clase de su proyecto por la parrilla de relectura anterior: ¿qué letra SOLID le duele más — y qué despiece propone?
- Puedo citar 3 patrones y su uso en una frase cada uno.
- Mi clase releída respeta S y D (o sé qué dividir).
- Sé cuándo NO añadir un patrón.
Preguntas frecuentes
¿Hay que aprender los patrones de diseño y SOLID, o es teoría superflua?
Ni superfluo, ni a aprender de golpe: son herramientas de diseño probadas que pagan en los proyectos que duran. Los patrones le evitan reinventar (mal) soluciones validadas, SOLID orienta hacia un código mantenible, y ambos dan un vocabulario común valioso en equipo. Sobre todo, los frameworks usan estos patrones: conocerlos es comprender Laravel y Symfony en lugar de imitarlos. Pero se aprenden progresivamente (un patrón a la vez, S y D primero), cobran sentido con la experiencia, y se aplican con criterio: un pequeño script no necesita arquitectura. Empiece por detectar los patrones en buen código, aplique en sus dolores reales — la teoría seguirá a la práctica.
¿Qué es la sobreingeniería, y cómo hallar el nivel justo de estructura?
La sobreingeniería es diseñar más complejo de lo que exige el problema: capas, interfaces y patrones donde bastaría una solución simple. Costes reales: complejidad inútil (difícil de comprender), más código que mantener, rigidez paradójica, tiempo perdido. La trampa clásica: entusiasmado tras aprender los patrones, se quieren aplicar en todas partes. Para hallar el nivel justo: parta del dolor real (¿test imposible? ¿duplicación? ¿modificaciones que lo rompen todo?) y elija la herramienta mínima que lo alivie; deje el código simple mientras no duela; relea con la parrilla SOLID para verificar, no para marcar. Ni catedral para una cabaña, ni cabaña para una catedral.
¿Qué son los patrones de diseño y para qué sirve SOLID?