¿Dónde está el programa?

¿Dónde está el programa? Esa fue la pregunta que hice a un programador de nuestro equipo. ¿Dónde está el código que describe como funciona nuestra aplicación? No pudo contestar y no esperaba que pudiera. En el proyecto que estábamos trabajando, la respuesta era bastante complicada. El programa estaba en todas partes y en ninguna a la misma vez.

Cuando comenzamos en este proyecto, lo primero que hicimos fue un prototipo. Bueno, el prototipo lo hice yo y sí, era “founder code”. Se escribió en poco tiempo y funcionó para validar la idea y para poder movernos adelante a conseguir clientes. Nunca me detuve a pensar en arquitectura o si podría escalar.

El único objetivo era que funcionara y que convenciera a clientes del potencial del producto. Misión cumplida.

Cuando le hice la pregunta al programador, al que llamaré Carlos, ya el proyecto era viejo en años de software y del “founder code” original quedaba muy poco, pero la falta de una arquitectura clara y definida todavía estaba presente. Luego de lograr los primeros clientes, en vez de repensar todo, optimizamos para velocidad y acumulamos mucha deuda técnica. Poco a poco los atajos que tomamos para movernos rápido nos estaban pasando factura.

Cundo le hice la pregunta a Carlos, ya llevaba unos meses estudiando sobre arquitectura de software. Antes de meterme en este tema cuando me hablaban de arquitectura pensaba en nuestra infraestructura en AWS. Que servicios estamos usando, si usamos Lambda, si estamos haciendo load balancing o estamos usando un “queue” y este tipo de cosas, nunca pensaba en la estructura de nuestro codebase.

Antes de esto tenía algunas nociones de arquitectura de software. Cuando conocí Ruby on Rail aprendí sobre Model, View, Controller y cuando empecé a hacer front end “en serio” usando Backbone.js hablábamos de client side MVC y MVVM. Desde entonces todos los proyectos que trabajé usaban algo parecido a MVC pero nunca me detuve a pensar por qué y si había algo mejor. Parecía funcionar y si todo el mundo lo está usando, creo que estamos ok.

Luego trabajé mucho con Django y uno de los “best practices” de la comunidad era la idea “fat models”. Lo que esto quiere decir es que lo que se puede implementar como un método de un modelo, lo debemos implementar como un método del modelo. En esos días, estaba muy pendiente a que no tuviéramos lógica regada por la aplicación y cuando había dudas sobre donde poner algo decía casi automáticamente, “fat models”. Tuve mucho éxito haciendo esto pero parecería que no aprendí nada.

Hoy llevo mas de un año estudiando sobre arquitectura de software. He aprendido mucho sobre como pensar acerca de la estructura de un proyecto de software y sobre que cosas funcionan en los codebases que trabajo y con los equipos que trabajo.

De todo lo que he estudiado lo más que me ha hecho sentido han sido acercamientos que se pueden considerar principalmente “object-oriented” pero vale la pena mencionar que lo que aprendí en mis años en el culto de “functional programming”, sigue siendo útil y lo uso todos los días. Una de las grandes ventajas de JavaScript, el lenguaje que uso principalmente, es que es multi paradigma y nos deja mezclar lo mejor de OOP y FP sin problema.

Cuando aprendí sobre domain-drive design o DDD, me hizo click inmediatamente. Todos los problemas que describían los había vivido y las soluciones que planteaban, no solo eran mejor para el codebase si no que también ayudaban a facilitar la comunicación entre el equipo e incluso los clientes. No voy ni a intentar definir DDD, pero es un tema que creo todo el mundo que le interese escribir software “mantenible” y “testiable” debe estudiar.

DDD, resultó ser una especie de puerta a un mundo de patrones de diseño y arquitecturas que ponen en el centro el “domain”.

El “domain” es la capa que contiene el programa. En el domain hay objetos que están diseñados para representar todo lo que existe en la aplicación, en el domain están todas las acciones que esos objetos pueden hacer y en el domain es imposible tener data en un estado inválido. En el domain no hay código específico de ningún framework o base de datos o cualquier otra dependencia de la infraestructura. Es lógica pura.

Esta era la respuesta que estaba buscando. De ahí me moví a aprender más sobre arquitecturas que usan esta idea de el domain en el centro de todo. Aprendí sobre Clean Architecture, Onion Architecture y Hexagonal Architecture o Ports and Adapters Architecture que es como prefiero referirme a este diseño. Todas estas arquitecturas aportan ideas valiosas y todas ponen el domain en el centro.

Para nuestro equipo llegamos a un diseño inspirado principalmente por Ports and Adapters Architecture. La experiencia hasta el momento ha sido positiva. Hacer cambios es fácil, es obvio donde están las reglas de negocio, nos obliga a ser mucho más explícitos y sentimos que escribimos menos bugs. Además hacer pruebas es fácil, rápido y casi divertido.

Recientemente, trabajando en un proyecto nuevo, después de semanas de haber comenzado, decidimos cambiar el web server library de Express.js a Fastify. El cambio tomó poco más de un día de trabajo y fue fácil lograr que todo funcionara luego del cambio. En el código del domain no cambiamos ni una sola linea.

Estoy seguro que ahora estarás pensando: ¿Pero cada cuánto tiempo se cambia de web server library? La repuesta es casi nunca, pero si puedo decir que el diseño que nos ayuda a hacer este tipo de cambios fácilmente, también nos ayuda de otras formas.

Por ejemplo, tenemos varias implementaciones de base de datos. Una para la base de datos de producción y otra que usamos en el ambiente de pruebas, que almacena los datos en memoria. También tenemos implementaciones de queues en SQS, Redis y una basada en archivos JSON en el file system. Durante development usamos la versión basada en archivos, en staging la versión Redis y en producción la de SQS y el código del domain siempre es el mismo. Los límites de cada capa y las interfaces entre ellas está claramente definidas y esto tiene muchos beneficios.

Esta experiencia me ha dado muchas herramientas nuevas y ha revivido mi entusiasmo por la disciplina de crear software.

Hoy todavía es difícil contestar la pregunta ¿dónde está el programa? pero todos en el equipo sabemos donde debe estar y cada día que pasa nos acercamos más a la meta. En algunos meses espero poder responder: “En el centro, el programa está en el centro”.

Foto: Unsplash