Patrones de diseño que arruinan tu código sin avisarte
⏱️ Tiempo de lectura estimado: 7 minutos
Patrones de diseño que arruinan tu código sin avisarte
Alguna vez abriste una PR, viste que alguien había implementado un Singleton o un Observer y pensaste "qué elegante"... hasta que tres semanas después nadie entendía por qué la aplicación tenía comportamientos extraños en producción. Me ha pasado. Y apuesto a que a ti también.
El problema no son los patrones de diseño en sí. El problema es que los aprendemos como recetas mágicas y los aplicamos con el mismo criterio con el que alguien pondría ketchup en todo: porque está ahí y parece buena idea.
Este artículo no es una defensa contra los patrones de diseño. Es una conversación honesta sobre cuándo se convierten en el enemigo silencioso de tu arquitectura.
Cuando los patrones de diseño se vuelven en tu contra
Hay una frase que escuché hace años en una conferencia y que no he podido sacarme de la cabeza: "Every pattern is a solution to a problem you might not have." Y tiene más verdad de lo que parece.
Los patrones de diseño nacieron para resolver problemas recurrentes en contextos específicos. El libro de la Banda de los Cuatro (Gang of Four) no decía "usa esto siempre". Decía "cuando te encuentres con este tipo de problema, considera esta solución". La diferencia es enorme.
El síntoma más claro de un patrón mal aplicado es cuando tienes que explicar por qué existe antes de poder explicar qué hace. Si tu código necesita un párrafo de justificación para entenderse, algo salió mal.
El Singleton: el más popular y el más mal usado
El Singleton es probablemente el patrón más implementado y el más incomprendido. La idea es simple: una sola instancia de una clase en toda la aplicación. Suena útil. Y lo es, en casos muy específicos.
El problema es que en mi experiencia, el 80% de los Singletons que he visto en proyectos reales eran básicamente variables globales con un traje elegante. Y las variables globales tienen una reputación por algo.
Cuando usas un Singleton para gestionar estado compartido entre componentes, estás creando acoplamiento implícito. Los módulos que lo consumen no declaran esa dependencia en ningún lado — simplemente la toman. Eso hace que el código sea difícil de testear, difícil de razonar y, cuando algo falla, difícil de rastrear.
Ojo que no digo que el Singleton sea malo por naturaleza. Un logger, una conexión a base de datos con pool controlado, configuración de entorno — ahí tiene sentido. El problema es usarlo como cajón de sastre para todo lo que quieres compartir entre clases.
El Observer: cuando la reactividad se convierte en caos
El patrón Observer es hermoso en teoría. Un objeto emite eventos, otros los escuchan, todo desacoplado y limpio. En la práctica, cuando tienes veinte observadores y un evento dispara una cadena de efectos secundarios que nadie documentó, estás ante lo que yo llamo "spaghetti reactivo".
He trabajado en sistemas donde rastrear por qué un cambio en el módulo A afectaba el comportamiento del módulo D requería abrir cinco archivos y rezar para que alguien hubiera dejado un comentario. Nadie lo había dejado.
El Observer no es el culpable directo, pero habilita ese tipo de arquitectura si no se gestiona con disciplina. Cuando lo uses, documenta explícitamente qué eventos existen, quién los emite y quién los consume. Si esa documentación se vuelve imposible de mantener, es una señal de que el patrón está escalando más allá de lo razonable.
Los patrones que más daño hacen en proyectos pequeños
Hay un fenómeno que ocurre con frecuencia en equipos que están aprendiendo arquitectura: el over-engineering por entusiasmo. Alguien lee sobre patrones de diseño, los entiende, y quiere aplicarlos. Eso está bien. El problema es cuando el contexto no lo justifica.
Factory Method en un proyecto de tres endpoints
Si tu aplicación tiene tres tipos de objetos y sabes con certeza que en los próximos seis meses no va a cambiar eso, implementar un Factory Method completo con interfaces, clases abstractas y factories concretas es ingeniería para un problema que no tienes.
El punto es que la complejidad tiene un costo. Cada abstracción que añades es una capa que alguien tiene que entender antes de poder contribuir. En un equipo pequeño o en una etapa temprana del producto, eso puede ser más perjudicial que útil.
Algo que me ha funcionado es aplicar la regla del tres: no abstraigas hasta que hayas visto el mismo patrón repetirse al menos tres veces en tu código. Antes de eso, duplicar puede ser más honesto que abstraer prematuramente.
Decorator sin un propósito claro
El patrón Decorator es poderoso cuando necesitas añadir comportamiento a objetos de forma dinámica sin tocar su clase base. Middleware en Express, pipes en Angular, wrappers de logging — tiene sentido.
Pero he visto proyectos donde los decorators se apilaban como capas de una cebolla sin ninguna razón evidente. Tres decorators encadenados para añadir funcionalidad que perfectamente podría vivir en un método bien nombrado. Ahora bien, si para entender qué hace tu objeto tienes que trazar mentalmente cinco niveles de wrapping, el patrón está trabajando en tu contra.
Cómo saber si un patrón de diseño está haciendo daño
No hay una fórmula perfecta, pero hay señales que no fallan. Primero: si nuevos miembros del equipo tardan más de lo esperado en entender una parte del código, y la razón es la arquitectura más que la lógica de negocio, algo está sobre-diseñado.
Segundo: si escribir tests para ese componente requiere montar un setup complejo de mocks y stubs solo para llegar a la funcionalidad real, el acoplamiento generado por el patrón es demasiado alto.
Tercero — y este es el más honesto —: si tú mismo, tres meses después de haberlo escrito, necesitas tiempo para recordar por qué tomaste esa decisión, eso no es un problema de memoria. Es un problema de diseño.
Los buenos patrones de diseño deberían hacer el código más legible, no menos. Si la aplicación de un patrón añade complejidad sin añadir claridad, es momento de cuestionar si era la herramienta correcta.
Antes de irte
Leer sobre patrones de diseño elegantes y luego mirar tu propio código puede ser desalentador. Esa sensación de "yo nunca escribiría algo así de limpio" es completamente normal y, honestamente, la hemos tenido todos en algún punto. El contraste duele, pero es exactamente eso lo que te hace mejorar.
La próxima vez que vayas a aplicar un patrón, hazte una sola pregunta antes: ¿qué problema concreto estoy resolviendo con esto? Si la respuesta es vaga, quizás el mejor patrón es no usar ninguno todavía.
¿Te ha pasado que un patrón de diseño terminó complicando más de lo que ayudó? Cuéntalo en los comentarios — esos errores son los que más enseñan.
Temas relacionados donde podrías enlazar: Refactoring sin romper producción, Clean Architecture en proyectos reales, Deuda técnica: cómo medirla y negociarla con tu equipo
Alt text sugerido para imagen destacada: "Diagrama de patrones de diseño con código de ejemplo en pantalla de laptop"
💬 Comentarios