Por nuestra experiencia, uno de los principales temas que más quebraderos de cabeza traen a los equipos de software de las empresas es tener mal definida o incluso no tener definida la estrategia del control de versiones.
Como ya hemos repetido muchas veces, tanto si la empresa quiere implantar integración continua como si no, el control de versiones es un punto clave en el desarrollo.
Feature branches
Nosotros normalmente, si los equipos son grandes, el trabajo se puede dividir en tareas pequeñas (1 día o 2 como mucho) y la herramienta de control de versiones que utilizan gestiona bien las ramas, solemos recomendar que opten por una estrategia de rama por historia de usuario (lo que se conoce como feature branches o task branches si hablamos de tareas, por si te encuentras alguna vez con estos términos).
Esta estrategia consiste en crear una rama por cada fragmento de trabajo que hagas.
En el caso de Scrum, consistiría en crear una rama por cada historia de usuario (feature branches) o crear una rama por cada tarea (task branches).
Cuando la historia esté terminada, se combina con la rama principal.
Así consigues varias cosas:
– El trabajo de cada desarrollador no afecta al resto, porque cada uno trabaja en su rama. Puedes subir código no terminado o que no funcione a la rama de la historia de usuario, sin temor a afectar al resto.
– De la misma manera, puedes decidir qué historias pasan a producción: las historias acabadas estarán combinadas con la rama principal, y las inacabadas o sin probar estarán subidas al control de versiones, pero en su rama correspondiente, sin combinar.
Luego si es necesario y aporta beneficio a la empresa, se puede pensar en hacer otras ramas por equipo, de integración etc. (Recuerda el post de ¿Qué estrategia de control de versiones seguir en un equipo Scrum?)
Para que te sirva un poco más de inspiración de estrategia de control de versiones con varias ramas te dejo algunos otros ejemplos, como Git flow y patrones de ramas.
Pero no es la única alternativa
No obstante, como suele pasar siempre, puede que para ciertos equipos esta no sea la mejor manera de enfocar el tema.
También nos encontramos con equipos que son más pequeños, han intentado implantar varias ramas y no les viene bien o cuya herramienta de control de versiones no gestiona bien las ramas, y quieren optar por tener una única rama en el control de versiones.
Ante este enfoque, ¿qué hacemos con las historias de usuario que no están acabadas? ¿No las subimos al repositorio?
En el enfoque de rama por historia de usuario, si una historia no estaba terminada (en la definición de terminada incluyo que haya pasado las pruebas de QA, bueno, mejor, en cualquier caso leé este post sobre el significado de terminaod, el «done») no se combinaba con la rama principal, pero el código aunque no esté terminado, está alojado en el control de versiones.
Déjame decirte, que el código debe subirse al control de versiones. Hay que subirlo, y frecuentemente, poco a poco, para evitar los problemas de integración.
Entonces… ¿lo subimos a la rama principal?. ¿Mezclamos entonces cosas terminadas con cosas que no lo están? ¿Y al subir a producción que hacemos?
Volviendo al enfoque de rama por historia de usuario, ante una subida a producción, puedes seleccionar qué ramas/historias están terminadas y subirlas (son las que están combinadas con la rama principal) y dejar las historias de usuario no terminadas sin subir.
¿Pero al tener solo una rama principal, cómo lo hacemos? ¿Y si queremos aplicar integración continua? ¿Cómo indicamos que para cierto código deben ejecutarse los tests y para otro no?
Bien, en este punto es donde entran las Feature toggles.
Feature toggles
Esta idea fue pensada hace unos años por Fowler y en las empresas recibe distintos nombres, como conditional features (en el equipo de Gmail), flags o flippers. Seguro que en algún momento habréis usado una idea parecida para otra cosa.
Para explicarlo de forma sencilla, una feature toogle es básicamente una sentencia if dentro de tu código. Si está activada (sentencia if ==true) se ejecuta el fragmento el código, y si no, el código no se ejecuta.
Esta práctica consiste en rodear cada historia/tarea/división del trabajo que implementes en una feature toggle.
Así los desarrolladores pueden subir tareas inacabadas a la única rama principal sin afectar al resto, siempre que la feature toggle de esa funcionalidad esté desactivada.
No obstante las feature toggles no tienen por qué ser solamente valores booleanos. Pueden ser strings, enumeraciones, enteros, cualquier cosa que se ajuste a tu flujo de trabajo.
Por ejemplo, imagínate que queremos migrar una base de datos a otra nueva.
Lo que podríamos hacemos entonces es que el código que gestiona la conexión con la base de datos esté en una feature toggle con estos 3 valores o algo que simbolice esto:
1 – Leer de la base de datos antigua.
2 – Leer de la base de datos antigua y pasar copias de seguridad a la nueva.
3 – Usar la nueva base de datos.
Si vamos un poco más allá, las feature toggles tienen más utilidades y aparte de poder subir código no terminado a la rama principal del control de versiones.
Por ejemplo, tienen utilidad a la hora de hacer pruebas, ya que activando el toggle la funcionalidad estará visible y se podrá probar.
O incluso a la hora de refactorizar, donde podremos tener conviviendo el código antiguo y el nuevo mientras que terminamos la refactorización y probamos que todo es correcto.
Si tienes Google Chrome, y quieres echar un vistazo a las feature toggles implementadas para este navegador, escribe chrome://flags en la url de Chrome.
¿Cómo implementamos las feature toggles?
Existen varias estrategias a la hora de implementar las feature toggles.
Se pueden implementar en el propio código, manteniendo algún fichero donde estén todas las feature toggles y si están activadas o no, o utilizar una base de datos.
Podemos incluso implementar que para ciertos usuarios las funcionalidades estén visibles y para otros no.
Incluso existen librerías que ayudan a la hora de implementarlas. Por ejemplo para Java están Togglz, ff4j (he de decir que no las he probado).
Consideraciones finales
Como vemos el uso de feature toggles tiene varias ventajas y puede verse como una alternativa a crear ramas por historias de usuario.
Sin embargo, hay que tener en cuenta también que el uso de feature toggles en el código disminuye la mantenibilidad del mismo y hace que se entienda peor.
Por ello hay que tener las feature toggles muy bien controladas, y eliminarlas del código una vez que la funcionalidad esté terminada y probada.
Además, si os fijáis, al subir el código a producción, estamos subiendo tanto la funcionalidad terminada como la que no lo está, aunque esta última no se ve. Por ello recalco que hay que gestionar muy bien las feature toggles y no dejar activadas feature toggles inacabadas.
En mi opinión, no es que una alternativa sea mejor que la otra. No soy partidaria de decir que las feature branches son mejor que las feature toggles, ni al revés.
Para mí, ambas son dos alternativas a tener en cuenta a la hora de gestionar nuestros equipos.
Incluso creo que no son exclusivas, y ambas ideas bien utilizadas, pueden convivir en los equipos, en función de lo que queramos conseguir.
- Debes crear apps sin saber programar (no hay que saber nada) + Crea Test con IA + Scrum es el nuevo Excel - 12 septiembre, 2024
- Las 6 técnicas prompting + 1ª Ley del Manager Oscuro + Mantenlo sencillo, estúpido - 5 septiembre, 2024
- Guía de Métricas Ágiles (versión agosto 2024) - 22 agosto, 2024
Me imagino la cantidad de «feature toggles» que tienen que existir en producción sin terminar pero que han subido arrastradas por otras y por no refactorizar estarán mucho tiempo en estado «dead code» 🙂
Enhorabuena por el post. Me gustaria indicar que el uso de feature flags no implica que el código sea menos legible y mantenible. Feature flag es una de las herramientas o técnicas que permiten implementar la estrategia branch by abstraction en el que desaparecen los merges, todo el codigo esta en master y siempre debe estar estable, todo nuestro código esta siempre sometido a nuestros pipelines de IC. Por otro lado, las nuevas funcionalidades se añaden como abstracciones. Además las FF nos permiten realizar Canary releases, A/B testing o Blue/Green Deployments. Indicar que efectivamente las FF tiene costes, p.e hay q eliminarlas junto al código antiguo para evitar feature zombies, en rendimiento ya que aunque parece ser un simple If las features normalnente se encuentran en un repositorio de features, gestión de features para evitar activar features erroneamente en pro. Feature flags es un gran poder y un gran poder conlleva una gran responsabilidad 😉