Cuándo evitar los principios SOLID en el código
Clean Code mal entendido: cuándo NO aplicar SOLID
Tiempo estimado de lectura: 8 min
- SOLID no es una religión ni un checklist.
- Aplicarlo mecánicamente puede aumentar la complejidad.
- Señales de mal uso incluyen optimización para extensibilidad hipotética.
- Casos típicos donde NO aplicar SOLID incluyen MVPs y scripts.
- Es un medio para gestionar cambio, no un fin estético.
Tabla de contenidos
- Qué es SOLID (y qué NO es)
- Clean Code mal entendido: cuándo NO aplicar SOLID (la idea central)
- Señales claras de que SOLID te está dañando
- Cuándo NO aplicar SOLID: casos típicos (con criterio)
- Un marco de decisión: aplicar SOLID “donde duele”
- Conclusión
- FAQ
Qué es SOLID (y qué NO es)
SOLID es un acrónimo de cinco principios de diseño orientado a objetos:
- S: Single Responsibility Principle (SRP)
- O: Open/Closed Principle (OCP)
- L: Liskov Substitution Principle (LSP)
- I: Interface Segregation Principle (ISP)
- D: Dependency Inversion Principle (DIP)
Su objetivo es gestionar el cambio: facilitar que el sistema evolucione sin romperse y sin que cada modificación se convierta en un efecto dominó.
Lo que SOLID no garantiza por sí solo:
- No garantiza simplicidad.
- No garantiza menos bugs.
- No garantiza buena arquitectura.
- No es “más clases = mejor diseño”.
- No es un requisito para todo tipo de código (scripts, automatizaciones, glue code, MVPs).
Clean Code mal entendido: cuándo NO aplicar SOLID (la idea central)
Cuándo NO aplicar SOLID no significa “ignóralo siempre”. Significa: no lo uses como objetivo, úsalo como herramienta cuando el coste lo justifica.
Aplica SOLID cuando el sistema tenga presión de cambio (frecuencia + riesgo + coste de cambio) suficiente para amortizar la abstracción. No lo apliques cuando estés pagando hoy complejidad para un cambio hipotético.
La presión de cambio suele venir de:
- requisitos variables,
- múltiples integraciones,
- equipos creciendo,
- reglas de negocio inestables,
- necesidad de testeo fino,
- alta criticidad (pagos, compliance, seguridad, SLAs).
Cuando eso no existe, SOLID “a tope” suele ser sobre-ingeniería.
Señales claras de que SOLID te está dañando
1) Estás optimizando para extensibilidad hipotética
Si la justificación es “por si acaso mañana…”, y mañana no llega, acabas con un sistema sobrediseñado. El OCP (abierto a extensión, cerrado a modificación) es valioso cuando hay variantes reales. Sin variantes reales, estás creando puntos de extensión vacíos.
Síntoma: Strategy, Factory, Provider por todas partes, con una sola implementación.
2) Tus abstracciones no comprimen complejidad: la multiplican
Una buena abstracción reduce el tamaño mental del problema. Una mala abstracción crea más términos y más saltos de archivo.
Síntoma: para entender un flujo tienes que abrir 12 archivos y recorrer 8 interfaces.
3) Dificultad para depurar y trazar el flujo
Si el diseño hace que el control flow sea “invisible” (inyección, factories, decorators, event buses) sin aportar beneficios tangibles, estás pagando en debugging.
Síntoma: el equipo tarda más en seguir un bug que en arreglarlo.
4) Más tests no significan mejores tests
DIP + mocks indiscriminados suele generar tests frágiles y acoplados a la implementación. Cuando cada cambio interno rompe 20 tests, el diseño está mal sirviendo al objetivo.
Síntoma: se “actualizan snapshots” o se reescriben mocks constantemente.
Cuándo NO aplicar SOLID: casos típicos (con criterio)
Caso 1: “MVP” real o funcionalidad exploratoria
Si estás validando un flujo de negocio, el valor está en aprender rápido. Introducir capas para “arquitectura perfecta” antes de confirmar el problema es un error.
Qué hacer en lugar de SOLID estricto:
- Código directo, con funciones claras.
- Separación básica: entrada/salida vs lógica central.
- Deuda técnica explícita en el backlog cuando haya señales reales de crecimiento.
Regla útil: si el código puede reescribirse en 1–2 días, no merece una arquitectura de 2 semanas.
Caso 2: Scripts, automatizaciones y glue code (especialmente con n8n)
En automatización, muchas piezas son pegamento: conectar APIs, transformar JSON, aplicar reglas simples. Aquí el objetivo es visibilidad, trazabilidad y fiabilidad operacional.
Pretender SOLID “clásico” en cada pequeño paso suele convertir una automatización en una mini aplicación innecesaria.
Qué aplicar:
- SRP a nivel de workflow (cada nodo con una responsabilidad clara).
- Buen logging y manejo de errores.
- Tipado ligero (si estás en TS) para entradas/salidas.
Si estás construyendo automatizaciones productivas y agentes que combinan APIs, validaciones, reintentos y observabilidad, tiene sentido apoyarte en un equipo que lo haga con criterio y operación real. En Dominicode Labs trabajamos precisamente en este tipo de sistemas: automatización y IA aplicada sin humo, con workflows mantenibles, trazables y diseñados para producción.
Caso 3: Frontend moderno (React/Next/Angular) y el exceso de “arquitectura enterprise”
En frontend se cae mucho en: services, repositories, usecases, controllers… para una UI que en realidad es un CRUD + queries. Esto no es “limpio”; es burocracia.
Cuándo NO aplicar SOLID al estilo backend:
- Cuando tu dominio es poco complejo.
- Cuando el principal cambio viene de UI/UX, no de reglas de negocio.
- Cuando el estado y el data fetching ya están encapsulados por frameworks/librerías.
Qué hacer:
- Componentes y hooks bien nombrados.
- Separar “UI state” vs “server state”.
- Mantener la lógica de negocio relevante en módulos puros (si existe).
Caso 4: SRP mal entendido → clases microscópicas
SRP no significa “una clase por método”. Significa “una razón para cambiar”. Si tus razones para cambiar son la misma (por ejemplo, la política de descuentos), agrupar es correcto.
Mal patrón:
OrderValidatorOrderValidator2OrderValidationContextOrderValidationService- … para validar 5 campos.
Mejor:
- Una función
validateOrder(order): ValidationResultclara. - Extraer funciones auxiliares cuando haya reglas con identidad propia (p.ej.
validateVatId,validateAddress).
Caso 5: OCP como excusa para no tocar código (y crear frameworks internos)
OCP no significa “nunca modifiques nada”. Significa “no rompas lo existente al introducir variantes”. Si para añadir una variante necesitas 4 nuevos archivos, un registro y una factoría, pero la variante es improbable, has creado un mini framework.
Señal: el equipo teme cambiar el código “por diseño”, y todo se resuelve con más capas.
Criterio:
- Extiende cuando tengas al menos 2–3 variantes reales o una roadmap clara de variantes.
- Si no, modifica el código de forma directa y refactoriza cuando el patrón aparezca.
Caso 6: LSP e herencia donde no toca
LSP va de sustitución: si B hereda de A, B debe poder usarse donde se usa A sin romper expectativas. En la práctica, la herencia en dominios “no matemáticos” suele generar jerarquías frágiles.
Cuándo NO aplicar “OO puro”:
- Si estás forzando herencia para reutilizar código.
- Si hay condicionales en la clase base para manejar subtipos.
Mejor:
- Composición sobre herencia.
- Estrategias explícitas solo cuando haya variantes reales.
Caso 7: ISP y el terror a “interfaces grandes”
ISP dice: no obligues a clientes a depender de métodos que no usan. Pero crear 7 interfaces para una clase con 5 métodos tampoco es virtud.
Cuándo NO aplicar ISP de forma extrema:
- Cuando la interfaz representa un concepto cohesivo.
- Cuando la granularidad solo añade fricción al wiring y al testing.
Mejor:
- Una interfaz por “rol” real del componente, no por método.
- Partir interfaces cuando existan consumidores claramente distintos con necesidades disjuntas.
Caso 8: DIP y el abuso de inyección para todo
DIP es poderoso, pero suele degenerar en: todo depende de interfaces, todo se inyecta, todo es mockeable. Resultado: más código ceremonial y tests acoplados al wiring.
Cuándo NO aplicar DIP en todas partes:
- En funciones puras: no necesitan inyección.
- En módulos de dominio sin IO: dependen de datos, no de servicios.
- En proyectos pequeños donde el wiring se convierte en el 30% del código.
Mejor:
- Mantener DIP en bordes del sistema: acceso a DB, HTTP, colas, filesystem.
- Pasar dependencias como parámetros en casos simples (sin contenedor DI).
- Preferir tests de comportamiento sobre mocks profundos.
Un marco de decisión: aplicar SOLID “donde duele”
En vez de discutir “aplicamos SOLID o no”, decide por zonas:
1) Núcleo de dominio (reglas de negocio)
Aquí SOLID suele rendir bien:
- SRP para separar políticas.
- OCP para variantes reales (métodos de cobro, pricing, permisos).
- DIP para aislar IO.
2) Bordes (integraciones, APIs, DB, colas, proveedores)
Aquí DIP y SRP son útiles, pero el objetivo es:
- observabilidad,
- resiliencia,
- contratos claros,
- manejo de errores.
3) Pegamento (orquestación)
En glue code, prioriza legibilidad lineal. Mucha abstracción suele empeorar.
Conclusión
Clean Code mal entendido: cuándo NO aplicar SOLID se resume en una idea: SOLID es un medio para gestionar cambio, no un fin estético. Si aplicas principios para “parecer profesional”, terminas con un sistema más difícil de entender, más difícil de depurar y más caro de evolucionar.
El enfoque senior no es “más patrones”, es más criterio:
- abstraer cuando hay presión de cambio,
- mantener el flujo simple cuando el problema es simple,
- diseñar para el presente con puertas abiertas al futuro, pero sin construir ese futuro por adelantado.
Y si ese “pegamento” entre sistemas (APIs, agentes, workflows, automatizaciones) empieza a crecer y a doler —en fiabilidad, en trazabilidad o en mantenimiento— es exactamente el tipo de contexto donde un enfoque pragmático marca la diferencia. Ahí encaja Dominicode Labs: construir automatización e IA aplicada orientada a producción, con arquitectura suficiente, sin ceremonias innecesarias.
FAQ
- ¿Qué es SOLID?
- ¿Cuándo debo aplicar SOLID?
- ¿Qué errores comunes se cometen al aplicar SOLID?
- ¿Cómo puedo simplificar mi código sin perder limpieza?
- ¿Cuáles son los principales principios de SOLID?
¿Qué es SOLID?
SOLID es un acrónimo que representa cinco principios fundamentales del diseño orientado a objetos que ayudan a construir software más mantenible y escalable.
¿Cuándo debo aplicar SOLID?
Deberías aplicar SOLID cuando el sistema tiene suficiente presión de cambio para justificar la complejidad adicional de la abstracción y el diseño.
¿Qué errores comunes se cometen al aplicar SOLID?
Algunos errores incluyen sobrediseñar sistemas que no requieren tanta complejidad, o aplicar principios de SOLID en situaciones de baja presión de cambio contradiciendo su objetivo.
¿Cómo puedo simplificar mi código sin perder limpieza?
Puedes emplear nombres precisos, funciones completas pequeñas, y mantener la separación de lógica y entrada/salida para mejorar la claridad sin complicaciones innecesarias.
¿Cuáles son los principales principios de SOLID?
Los principios son: Single Responsibility Principle (SRP), Open/Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP), y Dependency Inversion Principle (DIP).
