... Hay una forma
Antes hemos admitido que lo que la mayoría de los equipos quieren mejorar es el número de funciones entregadas y la calidad de la entrega (en número de errores). Pero ir a por ellos directamente significa una postura pasiva y reactiva. Para reducir los fallos, deberías haber prestado más atención, haber hecho pruebas más exhaustivas o haber pensado en tal o cual consecuencia imprevista. Para entregar más deberías haber codificado más rápido. Es difícil tener un plan para mejorar la situación desde este punto de vista.
La otra forma de pensar en esto es que el objetivo a largo plazo debería ser hacerlo tan bien como los equipos de alto rendimiento. Estos equipos son capaces de realizar varios despliegues al día, así que deberíamos avanzar hacia ese nivel de eficiencia.
Desplegar más rápido no significa simplemente establecer un calendario de despliegue más rápido y seguirlo a rajatabla. Sin duda esto acabará mal. Más bien debemos analizar nuestro proceso, detectar los cuellos de botella y eliminarlos de forma iterativa, para que el equipo se sienta naturalmente más seguro y cómodo aumentando la velocidad.
Estos cuellos de botella sugerirán los siguientes pasos que hay que dar para permitir la aceleración. A continuación se ofrece una enumeración, sin duda incompleta, de las situaciones en las que puede encontrarse un equipo y de las técnicas que pueden emplearse para resolverlas. La definición exacta de estas prácticas queda fuera del alcance de este escrito, pero se espera que despierten la curiosidad del lector. Más información en las referencias al final.
- Las historias de usuario tardan demasiado en completarse: Elaboración de historias de usuario más cortas. Rebanar (dividir un US grande en trozos más pequeños). Mejorar la arquitectura para facilitar los cambios. Permitir el despliegue a producción de código para características aún no terminadas (ramificación por abstracción, conmutación de funciones)
- Los codificadores suelen estar bloqueados a la espera de revisiones: Programación en parejas. Revisiones posteriores al compromiso.
- Aparecen muchos errores en producción y/o durante la fase de control de calidad: Más pruebas unitarias. Desarrollo basado en pruebas (TDD). Automatización de pruebas en general. Balas de rastreo (versiones mínimas de una función que tocan todas las partes de los sistemas afectados, para que todos los problemas salgan pronto a la luz). Conmutación de funciones (permite prácticas como el lanzamiento oscuro, o el lanzamiento canario, que hacen más seguro el lanzamiento de nuevas funciones, y también permite desactivar las funciones que se están comportando mal, mientras que el resto del servicio sigue funcionando).
- Al final del periodo, todas las funciones se integran al mismo tiempo, lo que provoca muchos conflictos: Desarrollo basado en troncos, o al menos en ramas de corta duración. Desacoplar la fusión del código de la finalización de una función. Rebanar. Programación por parejas y programación de conjuntos (Mob).
- Los requisitos de los productos cambian constantemente: Conmutación de funciones. Rebanar. Entrega continua (la cabeza de la rama principal siempre está lista para ser desplegada en producción. Véase más abajo).
- Los errores tardan demasiado en resolverse: Pruebas unitarias y desarrollo dirigido por pruebas (TDD). Entrega continua.
- Los despliegues suelen acabar en fracaso: Automatización del proceso de implantación
Los despliegues requieren mucho trabajo adicional: Automatización del proceso de implantación. Documentación automática.
Introducir estas técnicas no es ni fácil ni gratuito. Algunas de estas prácticas son habilidades difíciles y llevará tiempo y esfuerzo adquirirlas. Puede que sea necesario recibir algún tipo de formación o pedir a un desarrollador experimentado que se una al equipo durante un tiempo. Otras prácticas requieren una seria inversión de tiempo y trabajo para mejorar las herramientas internas del equipo.
No hemos mencionado las prácticas populares de IC/DC, que pueden definirse del siguiente modo:
IC: Integración continua. La práctica de integrar código en la rama principal del repositorio al menos una vez al día, cada confirmación desencadena una compilación del código y un conjunto de pruebas automáticas.
DC: Esto puede significar Despliegue Continuo o Entrega Continua (que de hecho se menciona como una de las prácticas recomendadas), que no son lo mismo. Despliegue continuo significa que cada confirmación se despliega automáticamente en producción sin intervención manual. La Entrega Continua es más relajada y significa que el código está en todo momento preparado para ser desplegado bajo demanda.
Estas son dos prácticas más amplias, que requieren para funcionar, de muchas de las técnicas mencionadas anteriormente (pruebas automáticas, canalización de despliegue automático, ramas de vida corta), por lo que no se adaptan tan bien a un enfoque de pequeños pasos. Sin embargo, pueden considerarse un hito intermedio o un requisito más general para alcanzar despliegues más rápidos.
Tampoco hemos mencionado otras buenas prácticas básicas que los desarrolladores deben seguir incluso antes de considerar las técnicas recomendadas, que consideramos prácticas ya aceptadas en el panorama actual de la codificación, y necesarias para una mejor experiencia de desarrollo en general, así como para un ritmo de despliegue más rápido. Algunas de ellas son el control de versiones del código mediante herramientas como git, entornos múltiples (desarrollo y producción, por ejemplo), convenciones de codificación para todo el equipo, etc.