L’ingénierie, c’est un peu comme le basketball
Anton Drukh
4 août 2016
0 minutes de lectureAujourd’hui, je veux m’intéresser à l’objectif de l’équipe d’ingénierie : livrer des fonctionnalités, et montrer ce qui nous aide à y parvenir chez Snyk. Plusieurs pratiques de notre cycle de développement s’articulent bien entre elles et nous permettent de livrer en continu. Je vais expliquer la philosophie qui sous-tend notre approche et présenter les pratiques de livraison continue que nous appliquons.
Livrer en continu
Livrer, c’est avoir un impact sur vos utilisateurs, et les bonnes équipes d’ingénierie livrent en continu. Vous pouvez appeler cela déployer, publier ou mettre en production : cela revient au même. Des technologies innovantes, des processus efficaces et un travail d’équipe qui donne de l’autonomie permettent d’atteindre cet objectif.
Dans les grandes organisations, il est courant de ne livrer une version que tous les quelques mois. Cela me fait penser aux matchs de football : il y a peu de buts, et beaucoup d’allers-retours sur le terrain. Chaque action demande beaucoup d’énergie, mais peu d’entre elles aboutissent.
Le basketball est une bonne analogie pour la livraison continue : dès que votre équipe a le ballon, elle dispose de 24 secondes pour tirer et marquer. Cela se répète si souvent pendant le match que cela devient la norme. Vous tentez constamment de marquer, en ne planifiant que l’action en cours, qui ne doit pas s’éterniser. La contrainte de temps est essentielle et contribue beaucoup à la nature du jeu.
Livrez tout !
Alors, comment faire de la livraison une habitude ? Est-ce que cela marcherait vraiment si vous arriviez au bureau aujourd’hui en proclamant : « Livrons tout en moins de 2 heures ! » ? J’en doute.
La philosophie peut se résumer à quelques principes :
1. Surmontez les obstacles : remettre à plus tard les tâches difficiles n’est jamais une bonne idée. Cela ne fait qu’inciter à livrer plus tard plutôt que plus tôt. Faites en sorte de vous attaquer dès que possible aux difficultés liées aux mises en production. Pour reprendre l’analogie du basketball, quand un défenseur vous fait face, ne revenez pas plus tard pour vous occuper du blocage.
2. Gardez le panier en ligne de mire : une fonctionnalité n’est qu’un moyen d’apporter plus de valeur à vos utilisateurs, pas une fin en soi. Comprenez leurs besoins et trouvez le meilleur rapport valeur/coût pour votre fonctionnalité. Au basketball, quand vous avez le ballon, levez les yeux vers le panier et optez pour la solution la plus directe.
3. Échouez rapidement : chaque fonctionnalité comporte des risques. Ne cherchez pas à élaborer un plan infaillible. Si quelque chose ne fonctionne pas, assurez-vous de le découvrir rapidement et recommencez. Au basketball, mieux vaut tenter un tir et le manquer que d’entendre l’arbitre siffler au bout de 24 secondes.
Les bonnes fusions, c’est l’absence de fusion
Quels sont les points difficiles d’une livraison qui deviennent encore plus compliqués quand on ne s’y attaque pas au plus vite ?
La fusion de vos modifications avec celles des autres est l’un de ces points douloureux. Les fusions peuvent virer au cauchemar. Tout ce dont nous aimons parler quand nous évoquons la « responsabilité collective du code » disparaît dès que je me retrouve face à 10 fichiers comptant chacun des dizaines de conflits. Imaginez cette joueuse de basketball qui fonce vers le panier : elle doit maintenant poser le ballon, prendre une pelle et creuser dans un tas de… terre. L’énergie du jeu retombe, et la prochaine fois qu’elle aura le ballon, elle cherchera la pelle au lieu du panier.
Une façon d’éviter cela consiste à répartir strictement les responsabilités, afin que les membres de l’équipe ne travaillent pas sur le même code pendant un sprint. Cette méthode peut fonctionner dans un environnement contrôlé, mais ce n’est pas notre cas. Des responsabilités cloisonnées vont à l’encontre de la responsabilité collective et favorisent une approche en silos de l’ingénierie. Cela ne donne pas d’autonomie à l’équipe, ce qui nuit à l’épanouissement individuel. Mieux vaut éviter cette approche.
Nous préférons avancer par petites étapes. Repensez à la dernière fois où vous avez dû gérer une énorme fusion pleine de conflits : combien de temps aviez-vous codé avant cette fusion ? Des semaines ? Des jours ? Il ne faut pas s’étonner que le code ait changé entre-temps : les autres travaillent aussi. Dès que vous écrivez la première ligne de code de votre prochaine fonctionnalité, anticipez. Visualisez le panier que vous visez : quand allez-vous intégrer votre code à la branche de la fonctionnalité ? Et mieux encore, quand le mettrez-vous en production ? Si la réponse dépasse une demi-journée de travail, repensez votre plan. Vous ne voulez pas entendre l’arbitre siffler au bout de 24 secondes.
Accélérez grâce aux feature flags
Chez Snyk, nous travaillons dans des branches personnelles qui sont créées, poussées, révisées, fusionnées et déployées en quelques heures. Pour les fonctionnalités plus importantes, dont le développement se poursuit sur plusieurs jours, nous utilisons des feature flags pour les mettre en production au même rythme, même si elles ne sont pas encore tout à fait prêtes. Nous partons du principe que le code lui-même est la meilleure documentation, et non un document de conception d’architecture. Si vous gardez vos plans pour vous dans une branche privée, non seulement vous ne visez pas une livraison rapide, mais vous n’aidez pas non plus les autres à avancer plus vite. N’oubliez pas les 24 secondes.
Les bons tests sont ceux qu’on fait tôt
Les tests sont l’autre point délicat lors d’une mise en production. Ils sont indispensables, mais le moment où vous les exécutez peut tout changer. Découvrir que quelque chose ne fonctionne pas comme prévu quelques minutes avant le déploiement est bien plus intimidant que de faire la même découverte quelques minutes après avoir écrit ce code imparfait. Pensez à tous ces changements de contexte : chercher la cause du bug, interrompre la partie de basketball en plein milieu, etc. Rien de réjouissant.
Sans être strictement orientés TDD, nous maintenons notre niveau grâce à une suite de tests complète, exécutée en local et pour chaque pull request. Nous nous efforçons de rendre les tests faciles à écrire et rapides à exécuter. Cela semble simple, mais exige beaucoup d’attention et, surtout, un sens des responsabilités. Un peu comme lacer ses chaussures avant le match : si vous savez que cela vous aide à marquer, vous ferez l’effort.
Passons à la pratique : nous ajoutons des tests aux nouvelles fonctionnalités, en particulier lorsque nous corrigeons ces bugs tenaces qui se sont glissés jusqu’en production. Nos dépôts GitHub sont intégrés à Travis CI, qui exécute la suite de tests pour chaque pull request et après chaque fusion dans les branches develop et master. Lorsque les tests réussissent sur develop et master, un déploiement automatisé est déclenché respectivement dans nos environnements de développement et de production, ce qui achève notre cycle de livraison continue. Nous proposons une option manuelle de « désactivation » du déploiement après une fusion, au moyen d’une chaîne secrète dans le message de commit. Je suis très heureux que cette option soit à désactiver, et non à activer. Je ne me souviens pas de la dernière fois où nous l’avons utilisée.
Le travail d’équipe est essentiel
Tout cela fonctionne grâce à l’accord de l’équipe sur la nécessité de livrer rapidement. Des fusions faciles sont le fruit d’un effort collectif, tout comme une suite de tests fiable. Elles demandent du temps, des efforts et un sens des responsabilités. Parlez des difficultés liées au processus de mise en production de votre équipe et apportez des changements progressifs. Privilégiez les gains rapides aux refontes complètes.
Vous avez une meilleure analogie que mon histoire de basketball ? Vous voulez partager les astuces qui font fonctionner votre équipe ? Dites-le-nous sur Twitter.
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.