Antecedentes
En el equipo de desarrollo de JPA tuvimos la suerte de iniciar un proyecto green-field para la gestión de métricas de equipos ágiles, JPA Metrics. El objetivo de este proyecto es llevar a una aplicación la experiencia adquirida en consultoría ágil sobre la aplicación de métricas. No pretendemos reemplazar las ventajas de contar in-situ con un gran profesional, pero sí que buscamos poder ayudar a más organizaciones en su transformación.
Cuando partes de cero tienes todas las decisiones frente a ti. Esto es genial, pero también abruma. No se si te pasa, pero a mi, tener un abanico tan grande de opciones, me puede bloquear. Como orgullosos ingenieros que somos, queremos tomar la mejor decisión para nuestro sistema. Queremos optimizar prestaciones por coste (con un presupuesto siempre muy limitado). Así que nos ponemos a analizar y a revisar. A sacar números (mis queridas hojas Excel) para ver qué nos conviene. Esto nos puede llevar a la tan temida “muerte por análisis”.
¿Merece la pena este esfuerzo anticipado? Mi experiencia me dice que raramente. En los proyectos grandes, la bola de cristal no funciona. Vamos aprendiendo y adaptando sobre la marcha.
François Truffaut decía en “La noche americana”, que el trabajo de un director de cine consiste en tomar decisiones. Mi experiencia en esta industria es similar. En muchas ocasiones, los compañeros se acercan a pedirme opinión sobre alternativas de diseño. Evalúo la información que me dan, elijo una opción y se van tan contentos. No saben que, muchas veces, las tomo al voleo. Cuando no hay criterios sólidos, es mejor probar algo que bloquearnos. Un mono con Eclipse y todo el tiempo del mundo hará el diseño perfecto.
Así, la aproximación más práctica es apostar por diseños emergentes. Es decir, aplazar las decisiones hasta el último momento (Last Responsible Moment), cuando disponemos de más información y experiencia para fijarla. No especulamos. Aplicamos los hechos ya confirmados a mi hoja de excel y elegimos lo que salga. Esto es puro Lean Development (sin certificación, ni leches).
En el desarrollo con infraestructuras on-prem, el riesgo de esta aproximación es muy alto. Hay que comprar la infraestructura y no tenemos ni tiempo ni dinero para estar probando. Pero con la computación en la nube, y más concretamente, con los servicios de PaaS, esto cambia. Podemos tomarnos el lujo de desarrollar sobre una plataforma provisional, para ir, poco a poco ajustando las decisiones que la consolidan.
Las plataformas flexibles nos permiten centrarnos en lo que realmente importa, la arquitectura del software. Mezclando a Robert C. Martin y a Jose Luis Cuerda:
La plataforma es contingente pero la arquitectura es necesaria.
Así, podemos elegir los componentes que más nos convengan, por precio, disponibilidad y conocimiento. Para luego ir reemplazándolos a medida que el proyecto avanza y tenemos requerimientos cualitativos concretos: disponibilidad, concurrencia, latencia, etc.
Esto puede dar un poco de miedito ¿Podremos cambiar la plataforma cuando tengamos decenas o cientos de miles de líneas de código? Para eso, tenemos que centrarnos en un diseño desacoplado, a nivel de lógica y (de nuevo) de plataforma. Algunas herramientas que me han resultado muy útiles son:
El Diseño Dirigido por Dominio
DDD nos ha funcionado muy bien a la hora de fragmentar el Dominio en bloques coherentes (Bounded Context) que se pudieran llevar a servicios independientes (microservices). También empleamos el catálogo básica de patrones DDD para el diseño de componentes: Entities, Value Objects, Aggregates, Services, Factories & Repositories. Extendemos este catálogo con patrones que nos ayudan a introducir desacoplamiento. No soy un friki de los patrones de software, pero si que son de gran ayuda a la hora de manejar el conocimiento sobre el diseño dentro del equipo.
Clean Architecture
Todos los días le ponemos una vela al Tío Bob para que nos oriente en la aplicación de diseños circulares (como hexagonales, pero sin vértices). Clean Architecture es nuestro patrón para la división en capas de los microservicios.
Test, test y más test
Este es mi mantra. El desarrollo IT es muy complejo…, testea a tu entrada y a tu salida y ya lo tienes hecho. BDD para definir cambios SMART y TDD como faro para el desarrollador.
Continuous Refactoring
Si tienes una cobertura de test que te da seguridad, el refactoring te sale natural. Es evidente que cuanto mayor sea el nivel, más costoso. No es lo mismo hacer refactoring de un componente que hacerlo de un módulo o de un servicio completo. Pero siempre es más realista que agarrarse al diseño preestablecido por su coste hundido.
Experiencia
Con arquitectura emergente, no quiero decir que contar en el equipo con experiencia no sea valioso. Todo lo contrario. Aunque partamos de una propuesta, no es lo mismo que el diseño esté basado en una práctica consolidada a que se improvise pintando cajas a lo loco. La experiencia en arquitectura de software nos va a evitar muchos ensayos y va a acelerar la evolución de la aplicación.
Las arquitecturas emergentes ponen nerviosos a los stakeholders
En JPA tenemos una reunión semanal donde todas las áreas dan visibilidad a su trabajo. Recuerdo que hace unos meses presenté los resultados de los test de carga, en nombre del equipo de desarrollo. Yo estaba muy orgulloso de que, por fin, hubiéramos conseguido complementar test funcionales con test automáticos sobre cualidades del sistema. La carga se generó sintéticamente (no teníamos usuarios reales) para una concurrencia que me pareció representativa y realista con la plataforma que empleamos en esos momentos: un dyno hobby en Heroku XD.
Al poco de terminar la reunión, Jerónimo me llamó. Quería hablar sobre las expectativas de la compañía para la aplicación y “sugerirme” algunas prácticas técnicas que nos podrían ayudar. Una luz roja se me encendió en la cabeza inmediatamente.
Para ingenieros novatos. Que tu jefe te diga como hacer tu trabajo no es una señal de interés. ES QUE ESTÁ PREOCUPADO.
Así que, a pesar de que ni de lejos era la intención de Jero, me planté en su casa con el portátil.
Yo le dije. “Te voy a explicar las decisiones técnicas que hemos tomado para garantizar el futuro de la aplicación”. Y él, puso cara de, “Ofús” :|
Abrí el IDE y le enseñé la arquitectura de la aplicación mediante la división del dominio en módulos, paquetes y componentes. Jero tiene conocimientos técnicos sobrados para entender el diseño. Pero, además, salta a la vista sin más que ver la organización del proyecto.
Revisamos el diseño RESTful del de backend y el uso de un cluster noSQL para proporcionar servicios escalables y efímeros.
Le mostré, en la práctica, como aprovisionamos a demanda los entornos de desarrollo y test en los equipos de trabajo y los de integración en el proveedor de cloud. Corrí los test automáticos mientras nos tomábamos una cerveza.
Le expliqué cómo evitamos las dependencias con proveedores: creando interfaces con la infraestructura y empleando contenedores. Hoy en día corremos sobre EKS y AKS y tardamos menos de una hora en tener la aplicación corriendo desde cero.
Revisamos las métricas de código en SonarCloud, la frecuencia de despliegue (varios por día), el tiempo de despliegue (<1h) y la tasa de errores por despliegue (<10%). Le hice una demo. Corregimos un error de UI mientras nos tomábamos otra cerveza.
Resultado
No me ha vuelto a llamar.
Bueno, si. Me pidió que le hiciera lo mismo a más gente (es un poco sádico). Y en ello estamos. Jero me ayudó a organizar los contenidos de una acción formativa sobre DevOps (ya disponible) y estoy preparando un taller práctico (picando código) que están sufriendo mis compañeros. Esperamos tenerlo listo en breve.
Para saber más:
Si te interesa saber más sobre nuestra formación DevOps, rellena este formulario para que te podamos enviar información.
[…] para que aprendiera qué es programar, para qué sirve el control de versiones o por qué una arquitectura monolítica puede superar en beneficios a una de microservicios en equipos pequeños y cross-funcionales. Por […]