La ingeniería se parece un poco al baloncesto
Anton Drukh
4 de agosto de 2016
0 minutos de lecturaHoy quiero centrarme en el objetivo del equipo de ingeniería de poner las cosas en producción y mostrar qué nos ayuda a lograrlo en Snyk. En nuestro ciclo de desarrollo seguimos varias prácticas que encajan bien entre sí y nos permiten entregar continuamente. Explicaré la filosofía detrás de nuestro enfoque y mostraré las prácticas de entrega continua que usamos.
Entrega continuamente
Entregar significa generar un impacto en tus usuarios, y los buenos equipos de ingeniería están entregando continuamente. Puedes llamarlo implementar, lanzar o poner en producción: todo significa lo mismo. La tecnología innovadora, los excelentes procesos y el trabajo en equipo que empodera ayudan a alcanzar este objetivo.
En las organizaciones grandes, es común lanzar una versión cada pocos meses. Me recuerda a los partidos de fútbol: se marcan pocos goles y hay mucho movimiento de ida y vuelta por la cancha. Se invierte mucha energía en cada jugada, y solo unas pocas tienen éxito.
El baloncesto es una buena analogía de la entrega continua: cuando tu equipo tiene el balón, tiene 24 segundos para lanzar y anotar. Esto se repite tantas veces durante el partido que se vuelve la norma. Siempre estás intentando encestar y planificas solo la jugada actual, que no puede tomar demasiado tiempo. La restricción de tiempo es fundamental y contribuye mucho a la naturaleza del juego.
¡Entrega todo!
Entonces, ¿cómo conviertes la entrega en un hábito? ¿De verdad funcionaría si hoy llegaras a la oficina y anunciaras «¡Entreguemos todo en 2 horas!»? Lo dudo.
La filosofía se puede resumir en unos cuantos principios:
1. Enfrenta los obstáculos: posponer las partes difíciles nunca es una buena opción. Solo incentiva a entregar más tarde en lugar de más pronto. Haz cuanto antes en el proceso todo lo que sea difícil de los lanzamientos. En términos de baloncesto, cuando te enfrentas a un defensor, no sigas adelante para ocuparte del bloqueo después.
2. Mantén la mirada en el aro: una función es solo el medio para aportar más valor a tus usuarios, no el objetivo. Entiende el requisito y encuentra la mejor relación entre valor y costo para tu función. En términos de baloncesto, cuando tengas el balón, mira hacia el aro y haz lo más sencillo.
3. Falla rápido: todas las funciones conllevan riesgos; no busques un plan infalible. Si algo no va a funcionar, asegúrate de descubrirlo pronto y empezar de nuevo. En términos de baloncesto, es mejor lanzar al aro y fallar que esperar a que el árbitro haga sonar el silbato al cumplirse los 24 segundos.
Las buenas fusiones son las que no se hacen
¿Qué tareas difíciles se vuelven aún más difíciles si no las abordas de inmediato?
Un problema de ese tipo es fusionar tus cambios con los de otras personas. Las fusiones pueden ser una pesadilla. Todo lo que nos gusta decir sobre la «responsabilidad compartida del código» se va por la ventana cuando veo 10 archivos con decenas de conflictos cada uno. Piensa en esa jugadora de baloncesto: corre hacia el aro por la cancha y, de pronto, tiene que dejar el balón, agarrar una pala y excavar entre un montón de… tierra. Se pierde la energía del juego y, la próxima vez que tenga el balón, buscará la pala en vez del aro.
Una forma de evitarlo es dividir las responsabilidades de manera estricta para que, durante un sprint, las personas no trabajen en el mismo código que sus compañeros. Aunque esta técnica podría funcionar en un entorno controlado, ese no es el entorno en el que trabajamos. Este tipo de divisiones estrictas va en contra de la responsabilidad compartida y fomenta un enfoque de ingeniería aislado. Esto no empodera al equipo, lo que perjudica el crecimiento personal. Es mejor evitarlo.
Nuestro enfoque consiste en trabajar en partes más pequeñas. Recuerda la última vez que tuviste que lidiar con una enorme fusión llena de conflictos: ¿cuánto tiempo llevabas programando antes de esa fusión? ¿Semanas? ¿Días? No debería sorprenderte que durante ese tiempo otras personas hayan hecho cambios en ese código: están trabajando a tu alrededor. Cuando escribas la primera línea de código de tu próxima función, piensa con anticipación. Visualiza el aro al que quieres lanzar: ¿cuándo integrarás esto en la rama de la función? Mejor aún, ¿cuándo lo pondrás en producción? Si la respuesta es más de media jornada de trabajo, replantea tu plan. No querrás oír el silbato del árbitro después de 24 segundos.
Avanza más rápido con los indicadores de funciones
En Snyk, trabajamos con ramas personales que se crean, se suben, se revisan, se fusionan y se implementan en cuestión de horas. Para las funciones más grandes, cuyo desarrollo avanza de forma incremental durante varios días, usamos indicadores de funciones para ponerlas en producción al mismo ritmo, aunque todavía no estén completamente listas. La premisa es que el código es la mejor documentación de sí mismo, no un documento de diseño arquitectónico. Si mantienes tus planes en privado dentro de una rama personal, no solo dejas de apuntar a una ejecución breve, sino que tampoco ayudas a quienes te rodean a avanzar más rápido. Recuerda los 24 segundos.
Las buenas pruebas son las que se hacen temprano
El otro punto problemático al lanzar una versión son las pruebas. Las pruebas son excelentes, pero el momento en que las haces puede marcar una gran diferencia. Descubrir que algo no es como pensabas minutos antes de la implementación es mucho más desalentador que hacer el mismo descubrimiento minutos después de escribir ese código imperfecto. Piensa en todos esos cambios de contexto: buscar la causa del error, detener el partido de baloncesto a la mitad, etc. No es nada bueno.
Aunque no seguimos estrictamente un enfoque de TDD, contar con una suite de pruebas completa que se ejecuta localmente y con cada pull request nos ayuda a mantenernos en forma. Nos enfocamos en facilitar la escritura de pruebas y hacer que se ejecuten rápido. Parece sencillo, pero requiere mucha atención y, sobre todo, responsabilidad. Es como amarrarse los cordones antes del partido. Si entiendes que te ayuda a anotar, harás el esfuerzo.
Ahora, los pasos prácticos: agregamos pruebas con las funciones nuevas, especialmente al corregir esos molestos errores que llegaron a producción. Nuestros repositorios de GitHub están integrados con Travis CI, que ejecuta la suite de pruebas con cada pull request y después de las fusiones a develop y master. Si las pruebas se ejecutan correctamente en develop y master, se activa una implementación automatizada en nuestros entornos de desarrollo y producción, respectivamente, y se completa nuestro ciclo de entrega continua. Tenemos una opción manual para cancelar la implementación después de una fusión mediante una cadena secreta en el mensaje del commit. Me alegra mucho que sea una opción para cancelar y no para activar. No recuerdo cuándo fue la última vez que la usamos.
El trabajo en equipo es clave
Lo que hace que todo esto funcione es el acuerdo del equipo de entregar rápido. Las fusiones sencillas requieren el esfuerzo de todo el equipo, igual que una suite de pruebas confiable. Exigen tiempo, esfuerzo y responsabilidad. Hablen sobre los puntos problemáticos del proceso de lanzamiento de tu equipo y hagan cambios incrementales. Prioricen los logros rápidos sobre las reformas totales.
¿Tienes una analogía mejor que la del baloncesto? ¿Quieres compartir trucos que hacen que tu equipo funcione bien? Cuéntanos en Twitter.
Empieza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.