Nous avons tous entendu un développeur dire “je préfère faire une branche à part, ce sera plus efficace”. Difficile de refuser sans contre-arguments.
Nous avons peut-être eu le même genre de réflexion en tant que développeur ou pour créer notre stratégie de test. Les problèmes apparaissent à moyen-terme quand nous essayons d’intégrer nos changements dans un système plus large et collaboratif.
La gestion des branches de développement est un véritable sujet impactant la productivité des équipes et au final, celle de l’entreprise.
Cet article fait le parallèle avec le risque associé à la multiplication de branches sur un repository logiciel. Nous partageons les questions à se poser pour utiliser le branching à bon escient, évitant les effets de mode.
Nous pouvons nous sentir bien (à court-terme)
Vous trouvez le projet dans le repository, faîtes un clone, commencez à développer.
Tout se passe à merveille, même la compilation se déroule correctement à la première exécution. C’est la voie rêvée pour développer vos fonctionnalités en toute tranquillité. En plus, personne ne vous demande de faire des commits réguliers sur le repo.
Ces objectifs sont loin des yeux, loin du cœur, et c’est tant mieux. Il ne faut même pas (encore) se préoccuper des changements effectués par d’autres membres de l’équipe. Pourquoi d’ailleurs, le focus est notre branche.
Des jours puis quelques semaines passent laissant le temps de peaufiner le développement et le test local des fonctionnalités. C’est d’ailleurs préférable car l’environnement d’UAT est souvent instable et manquant de données de test.
C’est vraiment plaisant de pouvoir coder tranquillement sans devoir se coordonner en transverse.
L’addition doit être réglée un jour ou l’autre
Le chef de projet revient de vacances et vous demande si la fonctionnalité sera testable le lendemain en UAT. Vous répondez “Aucun problème, j’ai même eu le temps de bien tester” tout en lançant un push sur le repository principal.
Le temps de chargement paraît anormalement long sur votre dernier Macbook M1, bizarre, sûrement le moment de prendre un café. À votre retour, la taille du changelog et sa liste de conflits difficiles à scroller vous rendent nerveux.
Je vous passe les prochains heures à essayer de comprendre quel portion de code intégrer, sans réussir à compiler et encore moins à tester. Le lendemain, malgré tous vos efforts, votre branche et ses fonctionnalités ne sont toujours pas disponibles.
Cette situation de trade-off du court-terme est encore vécue dans beaucoup d’équipes. Le sujet de collaboration transverse sur la base de code est largement sous-estimé.
Une vision locale autocentrée fait souvent mal
Ce type de perspective se traduit dans la citation initiale utilisant la 1er personne : “je préfère travailler une branche seule”.
Le sytem-thinking défend une vision holistique d’un système, favorisant l’impact global au-delà d’optimisations uniquement locales. Nous devons appliquer le même raisonnement au développement logiciel et à la gestion des branches.
La problématique n’est pas de créer une branche. Nous pouvons créer une branche pour favoriser un processus de revue, tout en maintenant des commits ou actualisations régulières. Le danger est dans la distanciation de notre branche avec notre projet principal.
En tant qu’humains nous avons du mal à intégrer l’impact des fameuses delayed feedbacks loop. Nous anticipons encore moins leur impact au plus nous sommes personnellement et émotionnellement impliqués. Pensez aux tentatives de régimes pratiqués avec un pot de glace devant une série.
Nous pouvons donc facilement prendre des décisions locales se révélant coûteuses à moyen-terme. Nous pouvons presque perdre de vue le modèle de branching retenu par l’équipe.
Nous pouvons faire des branches sans utilité
Les modèles de gestion de branches sont intéressants pour mettre en perspective plusieurs pratiques face à des problématiques communes. Mais comme pour les pyramides de tests, le contexte, le bon sens et l’adaptation restent clefs pour qu’une valeur soit captée.
Nous nous laissons facilement guider par des habitudes comme la vérification intensive d’emails ou de notifications. Nous pouvons également tomber dans le même travers dans la gestion de nos branches, à créer à tout va et pour tout usage une branche : par feature, par release, de hotfix pour chaque release, cela semble sans fin.
Notre objectif est de sélectionner un modèle de gestion de branche aligné avec notre organisation, culture et modèle de repository. Si deux modèles semblent adaptés, le plus simple doit être retenu pour contenir la complexité. Ces étapes sont essentielles afin d’éviter d’avoir 10 branches faisant perdre 10 heures par changement de fonction à un développeur.
Sans rentrer dans le détail, si Git Flow est le modèle que vous avez retenu, prenez du temps pour identifier les facteurs vous guidant vers ce choix. Vous pouvez être en train de procrastiner le traitement de root causes sur votre chaîne de développement.
Nous pouvons manquer de courage
La procrastination est un mécanisme humain transmis par les générations précédentes. Celles qui ont conservées leur énergie ont plus largement survécues à des attaques de lion et autres surprises.
Comme le manque de sport pour nous, la procrastination est par contre dangereuse pour le logiciel.
Nous avons facilement peur d’intégrer régulièrement notre code, la compilation va-t-elle passer? Est-ce que je vais bloquer mes collègues? Si je pousse mes développements jusqu’en UAT, comment réussir à tester sans avoir des jeux de données et d’outillage à disposition? Autant de questions d’intégration trop souvent négligées.
Des pratiques existent comme les features flags, les quality gates en CI/CD, des outils d’automatisation, etc. Encore faut-il en assurer leur implémentation et alignement avec les objectifs du système. C’est ici que nous arrivons pour moi au Quality Engineering qui doit agir en transversalité et avec impact.
En guise d’inspiration, vous pouvez consulter cet article relatant les investissements et choix défendus par Google durant des années pour la performance de sa chaîne logicielle : How Googles Does Repo (à venir).
Des branches minimales dans un système intégré
Centré autour d’une expérience de développement caricaturée, nous retrouvons les éléments importants à considérer dans notre gestion de branche.
Nous devons choisir la solution minimale support un cycle rapide d’itération de nos équipes. Cela veut donc dire permettre une intégration, déploiement et testing dans l’ensemble des environnements. Nous devons créer un écosystème laissant peu de place à la procrastination ou à l’envie de travailler en silo.
En note personnelle, au plus le système semble complexe, au plus de questions nous devons nous poser. Notre travail est de contenir la complexité pour soutenir la performance d’une organisation. Pour cela, simplifiez, réalisez des commits régulièrement déployés jusqu’en production.
N’oubliez pas les features-flags et autres mécanismes d’activation progressifs, au risque de faire mal.