Código que funciona vs. Software diseñado: Lecciones de una década
El artículo reflexiona sobre la diferencia entre programar para que algo funcione y diseñar software para que sobreviva al tiempo. Basado en una década con Django, advierte que la arquitectura no es el framework, sino las decisiones que determinan qué tan caro será cambiar el sistema mañana.
Este texto forma parte de una serie sobre arquitectura de software en la práctica.
No es una serie para aprender patrones de memoria ni para copiar estructuras de carpetas. Es una serie pensada para quienes ya saben programar, ya han construido sistemas reales, y empiezan a notar que hacer que el código funcione no siempre es suficiente.
Lo que sigue no es una explicación técnica, sino una historia. Una experiencia real y un punto de partida.
Una historia real sobre sistemas que funcionan… hasta que cambian
Aprendí Django como muchos lo han aprendido: haciendo que funcione.
Un modelo aquí, una vista allá, un formulario que guarda datos, una página web que responde. El framework ayudaba. Mucho. Durante bastante tiempo parecía tener una respuesta para todo. El sistema creció. El negocio estaba contento. Yo también.
Y sin que me diera cuenta, confundí dos cosas: el sistema funciona con el sistema está bien construido.
No fue inmediato. Nunca lo es. El problema no apareció el primer mes, ni el primer año. Apareció cuando tuve que cambiar algo que "ya estaba probado".
Apareció cuando una regla de negocio dejó de ser una excepción y pasó a ser la norma. Apareció cuando una decisión tomada hace años empezó a condicionar todo lo que se quería hacer después.
Años después, al enfrentarme de nuevo a mi propio código, tuve ese momento de claridad incómoda en el que entiendes que hiciste lo mejor que sabías hacer… pero eso ya no era suficiente.
El código funcionaba, sí, pero cada cambio costaba más. Cada ajuste requería tocar lugares que no tenían nada que ver. Cada nueva persona en el equipo necesitaba semanas para entender cómo funcionaba el sistema.
Y no porque el framework estuviera mal. No porque yo hubiera programado "mal".
Sino porque nunca diseñé el sistema como algo que fuera a sobrevivir al tiempo. Solo se diseñó para resolver los problemas del momento.
Durante años escribí código, mucho código. Código correcto, incluso elegante a ratos. Pero escribir código no es lo mismo que diseñar software. Y diseñar software no es lo mismo que construir sistemas que puedan cambiar sin romperse.
Esa diferencia no se nota cuando estás solo. Ni cuando el proyecto es joven. Ni cuando el negocio todavía no sabe bien qué quiere. Se nota cuando el sistema empieza a pedir cosas que no estaban en el plan original.
Entonces aparecen frases conocidas:
"Es que esto siempre ha sido así."
"Mejor no toquemos eso."
"Eso está muy acoplado."
"Primero que funcione y luego lo ordenamos."
Esta última es especialmente peligrosa, porque casi siempre es honesta. Nadie la dice con mala intención. El problema es que el "luego" rara vez llega. Y cuando llega, ya no es una refactorización: es una cirugía.
Aquí suele aparecer otra confusión común: pensar que arquitectura es sinónimo de framework. Que cambiar de stack va a arreglar el problema. Que si hoy duele con una tecnología, mañana dolerá menos con otra.
Pero el problema tampoco era el framework.
Un problema de diseño... o de su ausencia
Con el tiempo entendí que el problema no era solo el sistema, sino los procesos que ese sistema estaba modelando.
Cuando un proceso no está diseñado, el sistema termina diseñándolo solo. No por malicia, sino por inercia. Por costumbre. Por economía. Se toman decisiones con lo que se conoce en ese momento y con los recursos disponibles en ese momento. Nada más.
El resultado suele funcionar, pero solo mientras el contexto no cambia.
Diseñar un sistema de software debería parecerse más a diseñar un edificio. No se trata de adivinar el futuro, sino de asumir que habrá cambios: más personas, nuevas reglas, otros usos. Y que si eso no se piensa desde el inicio, el sistema crecerá igual… pero sin forma.
A eso es a lo que llamamos arquitectura.
Arquitectura es el conjunto de decisiones que determinan qué tan caro será cambiar mañana.
Y eso no se arregla después.
Por eso aprender arquitectura tarde es tan frustrante. Porque cuando uno intenta hacerlo, el sistema ya está lleno de decisiones invisibles que ahora son intocables. Entonces la arquitectura parece exagerada, burocrática, innecesaria. Parece algo que estorba.
En realidad, estorba porque llega tarde.
Aquí también suele aparecer el tema del testing. No como disciplina, sino como dolor. Tests que cuestan escribir, que se rompen con cualquier cambio, que parecen más frágiles que el propio código. Eso tampoco es casualidad. Cuando el diseño es confuso, los tests lo son aún más.
Nada de esto se ve el día uno. Todo esto se ve con el tiempo.
Y el tiempo es el verdadero juez del software.
Una lección que llega tarde
Este texto no nace de una discusión teórica ni de una moda arquitectónica.
Nace de un sistema real.
Un sistema construido hace más de una década, que funcionó durante años.
No como demo. No como experimento académico.
Funcionó en producción, con usuarios reales, procesos reales y consecuencias reales.
Durante mucho tiempo fue motivo de orgullo. Con razón.
Estaba bien pensado, era modular, resolvía problemas complejos y sostenía a una organización completa. No era código improvisado. Había criterio, intención y oficio.
Y sin embargo, con el paso del tiempo, empezó a mostrar otra cara.
No se rompía.
No fallaba.
No colapsaba.
Simplemente cada cambio costaba más.
Decisiones razonables en su momento comenzaron a condicionar todo lo demás. Ideas nuevas tenían que adaptarse a estructuras viejas. Cambios pequeños requerían tocar lugares que no tenían nada que ver. El sistema seguía funcionando, pero cada ajuste pedía permiso al pasado.
Incluso sistemas bien pensados pueden convertirse en cárceles si no se diseñan para cambiar.
Un nuevo comienzo
No se trata de señalar errores ni de reescribir la historia con soberbia retrospectiva. Las decisiones tomadas entonces fueron válidas en su contexto. El problema fue no incorporar explícitamente algo que hoy sabemos que es central: que los sistemas crecen, cambian y exigen adaptabilidad.
Por esa razón he decidido crear un proyecto personal.
No para reemplazar nada.
No para corregir el pasado.
Sino para aplicar, desde el inicio, todo lo que esa experiencia dejó.
Un proyecto donde las decisiones importantes se tomen de forma consciente desde el principio. Donde el cambio no sea una excepción incómoda, sino una condición asumida. Donde se diseñe aceptando que el sistema puede evolucionar de formas que hoy no podemos prever, y que quien lo construye no siempre estará ahí para explicarlo.
No para evitar errores, sino para no volver a tomar decisiones válidas solo en su contexto original, pero frágiles frente al crecimiento y al cambio.
Todavía no importa cómo.Primero había que entender por qué.
Hasta aquí no hemos hablado de arquitectura.
No de verdad.
Hemos hablado de tiempo, de cambio, de sistemas que crecen más allá de la intención original de quien los escribió. De decisiones que funcionaron, pero que hoy pesan.
La adaptabilidad no es un efecto secundario. Es una propiedad que o se diseña o no aparece.
Y diseñarla implica aceptar algo incómodo: que el sistema va a cambiar, y que nosotros no siempre estaremos ahí.
Si alguna de estas ideas te incomoda, no es casualidad. A mí también me incomodaron.
Ahí es donde empieza todo lo demás.