Producto de SoftwareJosé terminó de hacer un refactor en parte del código en el procesamiento de un sitio web. Como era un arreglo menor, José la terminó y siguió con la tarea siguiente.

Cuando se desplegó el código en producción dos semanas después, todo el sitio se cayó. Un único caracter mal escrito, que no se detectó con las pruebas automatizadas, ocasionó una falla en cascada que provocó la caida general. Llevó ocho horas poder aislar el problema, arreglar este único caracter mal escrito, desplegarlo y volver a tener el sitio productivo en linea. ¿Podrá hacer algo José para evitar que estos problemas vuelvan a ocurrir?

José le hecha la culpa a la mala suerte, a la naturaleza imperfecta del ser humano, a los costos inevitables de la ingeniería del software, y finalmente sigue con la siguiente tarea.

Esta es la historia todos los días en muchísimas organizaciones. Y apesta. José tiene un problema, y ni siquiera sabe que lo tiene: sus prácticas de despliegue no son sustentables. Esos "errores tontos" , como el que cometió, van a incrementarse a medida que crezca el producto y se vuelva más grande y complejo. José necesita implementar una solución escalable.

Soluciones que no son soluciones

Antes de ver esta solución, repasemos algunas no-soluciones comunes. Aunque los puntos siguientes son soluciones a problemas reales, estas soluciones no van a resolver el problema de José.

1. Más pruebas manuales

Obviamente, las pruebas manuales no escalan con la complejidad. Y tampoco se pueden encontrar todos los problemas, porque los ambientes de pruebas nunca van a ser exactamente igual al productivo.

2. Más planificación al inicio

La planificación al inicio es como el condimento en las recetas de cocina: es dificil decir cuánto es poco y cuánto es mucho. Lo que si se sabe es que no hay que agregar ni de más ni de menos, porque en ambos casos se arruina la comida. La tendencia natural a sobre-planificar radica en concentrarse en temas sin importancia. Lo único que lograremos es seguir cometiendo errores tontos, pero ahora van a ocurrir sobre requerimientos que no les importa a nadie.

3. Más pruebas automatizadas

Las pruebas automatizadas son muy buenas. Y más pruebas automatizadas son incluso mejor. Pero no hay ninguna cantidad de pruebas automatizadas que puedan asegurar que una característica vaya a sobrevivir al uso humano, porque ninguna prueba automática se tan brutal, aleatoria, maliciosa, ignorante o agresiva como la suma de todos los usuarios del sistema.

4. Revisiones de código y programación en parejas

Ambas son excelentes prácticas. Incrementan la calidad de código, previenen defectos y educan a los desarrolladores. Estas prácticas ayudan muchísimo a mitigtar defectos, pero en última instancia están limitadas por el hecho de que, aunque dos personas piensan más que una, ambas siguen siendo humanas. Las revisiones de código y la programación en parejas sólo van a detectar errores que la organización ya es capaz de descubrir.

5. Entregar más seguido

Aunque esto puede disminuir el tiempo de una caida (algo se rompe, hacemos un rollback), el costo en los tiempos de desarrollo por el trabajo y el retrabajo va a ser alto, y los errores van a seguir apareciendo. La tendencia natural sería entregar con menos frecuencia, hasta que no entreguemos nada. Y entonces nos vamos a ver forzados en re-escribir todo el código. Lo cual está condenado a fracasar también.

La solución: despliegue continuo

Entonces, ¿qué debería hacer José? Dos palabras: Despliegue Continuo. Cada commit debería ser desplegado instantáneamente a producción. Repasemos la historia de José una vez más, asumiendo que hubiera tenido una implementación ideal de Despliegue Continuo. José realiza el commit. Mintuos más tarde surge una advertencia indicando que el cluster está caido. La falla se relaciona con el cambio de José, con lo cual se revierte el cambio. José prácticamente no pasa tiempo haciendo debug, y puede encontrar muy facil el error que cometió. Su error causó una falla en cascada, pero el tiempo de caida fue mínimo.

El Despliegue Continuo es la implementación del patrón clásico Fail Fast (Fallar Rápido) para un proceso de entrega de software. Mientras más cerca ocurra un error del punto en el que fue introducido, más datos vamos a tener para corregir dicho error. En el código, Fail Fast signifca que debemos lanzar una excepción ni bien detectamos parámetros o entradas incorrectas, en vez de esperar a que algo se rompa más adelante. En un proceso de entrega de software, Fail Fast significa entregar código a producción lo más rápido posible, en vez de esperar a todo un ciclo semanal o mensual (¡o más!) para que algo se rompa.

El Despliegue Continuo es muy simple: hay que entregar el código a los clientes lo más rápido que podamos. Quizás hoy signifique hacerlo semanalmente en vez de mensualmente, pero con el tiempo vamos a poder acercarnos al ideal, e iremos viendo los beneficios en todo este proceso.

Basado en Continous Deployment, por Timothy Fitz.

Inspiración.

"Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

Bernard Shaw