Un playbook pratique pour gérer une équipe de dev à distance
Un QA, huit personnes, une base de code multi-locataire et trop de bugs en prod. Voici les cinq cérémonies qu'un nouveau lead a utilisées pour corriger ça, avec la manière exacte dont on mène chacune.
Nous sommes huit, entièrement à distance : un lead, quatre développeurs, deux personnes produit (dont une designer) et un QA. On construit un produit multi-locataire : une base de code partagée, plus des fonctionnalités spécifiques à certains locataires.
Pendant un temps, ça ne marchait pas. Des bugs atteignaient la production régulièrement. On prenait le travail au fil de l’eau. Personne n’avait une vision claire de ce qui allait sortir ensuite. Et un seul QA ne peut pas couvrir quatre développeurs sur une base de code où un changement pour un client peut silencieusement casser un autre.
Puis un nouveau lead est arrivé. Il n’a pas réécrit notre processus depuis un manuel. Il a introduit cinq cérémonies, une à la fois, chacune visant un problème précis qui nous faisait mal. Voici le playbook : ce qu’est chaque cérémonie, exactement comment on la mène, et ce qui a changé.
Une réserve honnête d’emblée : on ne fait pas de sprints à durée fixe. Quand je dis “revue de sprint” plus bas, lisez “revue de release”. On mène des cérémonies régulières sur un flux de travail continu, pas du Scrum de manuel. Je pense que c’est très bien, et j’y reviendrai à la fin.
Livrer moins de bugs : mettre la qualité dans le ticket, pas seulement dans le QA
Les pires bugs qu’on a livrés étaient par locataire : un changement pour un client en cassait un autre. On ne peut pas recruter assez vite pour s’en sortir. La seule chose qui passe à l’échelle, c’est de déplacer la qualité plus tôt, avant qu’une ligne de code soit écrite. Le nom du milieu, c’est “shift left”, et les chiffres sont sans détour : les exigences ambiguës ou incomplètes sont mises en cause dans environ 50 à 60 % des défauts en production, et un bug attrapé au stade des exigences coûte une fraction du même bug attrapé en production.
Les défauts au stade des exigences (critères d’acceptation ambigus, cas limites oubliés, règles métier contradictoires) représentent environ 50 à 60 % des défauts en production, et les équipes qui déplacent le QA vers l’amont réduisent radicalement les coûts de défauts par rapport à celles qui attrapent les bugs en production.
Source : synthèse des données de l’IBM Systems Sciences Institute et du World Quality Report de Capgemini
Alors on a changé ce qu’un ticket doit contenir avant que quiconque le prenne.
Chaque ticket reçoit des critères d’acceptation avant d’être estimé. Pas un titre vague. Une liste concrète de ce qui doit être vrai pour que le ticket soit terminé.
Si un ticket est flou, il passe d’abord par une investigation. On n’estime pas quelque chose que personne ne comprend. Un court spike répond aux questions ouvertes, et seulement ensuite on le dimensionne. Ça a tué à lui seul toute une catégorie de bugs du type “on n’avait pas réalisé que ça touchait aussi X”.
La règle multi-locataire : chaque ticket nomme le rayon d’impact. Comme nos pires échecs étaient inter-locataires, chaque ticket répond à une question explicitement : est-ce que ça touche du code partagé ou un seul locataire, et si c’est partagé, quels locataires faut-il vérifier ? Cette seule ligne transforme un risque invisible en case à cocher.
Voici un modèle qu’on colle dans chaque ticket non trivial :
## Critères d'acceptation
- [ ] Étant donné <état>, quand <action>, alors <résultat>
- [ ] Cas négatif : étant donné <mauvaise entrée>, alors <géré comment>
## Rayon d'impact
- Touche : [ ] cœur partagé [ ] un seul locataire
- Si partagé, locataires à vérifier : <liste>
## Comment tester
- <étapes que le QA peut suivre sans nous demander>
Voici la partie qu’on n’a pas complètement résolue, et je préfère être honnête là-dessus. Aujourd’hui, c’est le créateur du ticket qui écrit les critères d’acceptation, et nous, les développeurs, écrivons les notes “comment tester”. Ça marche jusqu’à ce que ça ne marche plus : parfois ces notes sont trop minces, le ticket est marqué prêt pour la release, et il n’aurait pas dû l’être. La cause profonde n’est pas qui a tapé les notes. C’est que l’auteur s’auto-certifie de fait. La personne qui a écrit le code est la dernière qui devrait être la porte qui dit “c’est livrable”.
Là où je pense que ça doit aller, c’est une version allégée de ce que le milieu appelle les “Three Amigos” : produit, QA et un développeur qui façonnent les critères ensemble, le produit possédant le “quoi”, le QA possédant “ce qui peut casser”, le dev possédant “ce que ça touche”. On ne mène pas encore cette cérémonie. Mais même une Definition of Ready légère aiderait, et la porte de release devrait être quelqu’un d’autre que l’auteur, le QA quand c’est possible, un pair quand le QA est débordé.
Voici la checklist vers laquelle on converge. Cochez-la contre votre propre prochain ticket :
Ce ticket est-il vraiment prêt ?
Cochez ce qui est vrai pour votre prochain ticket.
Le filet anti-régression : les mêmes cas, testés avant chaque release
Les critères d’acceptation arrêtent les nouveaux bugs. Ils ne font rien pour l’ancienne fonctionnalité qui casse silencieusement quand on touche au code partagé. Pour un produit multi-locataire, c’est l’échec le plus dangereux de tous, et il lui faut sa propre garde : un ensemble fixe de vérifications qui tourne avant chaque release, pas par ticket.
Il y a deux versions acceptables de ça, et vous devriez grimper de la seconde vers la première :
- Des tests end-to-end automatisés couvrant les chemins critiques : la connexion, le workflow principal, la facturation, et les fonctionnalités par locataire qui divergent du cœur partagé. Suite verte, ou pas de release.
- Au minimum, une liste écrite de scénarios obligatoires, un jeu par client important, que le QA déroule avant chaque release. Rien ne sort tant que cette liste n’est pas verte.
La règle multi-locataire s’applique ici aussi : la liste doit inclure au moins un scénario pour chaque locataire dont le comportement diffère du cœur partagé, parce que c’est exactement là qu’un changement “inoffensif” explose. Et la liste est un cliquet : dès qu’une régression passe, son scénario y est ajouté, pour que le même bug ne puisse plus jamais atteindre la production deux fois.
C’est la différence entre “on a testé ce qu’on a changé” et “on a prouvé qu’on n’a pas cassé ce qu’on n’a pas touché”. Seule la seconde garde un produit multi-locataire stable à mesure qu’il grandit.
Ce qui a changé malgré tout : plus de tickets sont réellement prêts pour la release, parce que plus d’yeux les traversent avant d’y arriver. L’écart restant, c’est l’auto-certification ci-dessus, et le nommer est le premier pas pour le refermer.
La rétro : un board Miro, et des votes qui forcent la priorité
À la fin de chaque release, on ouvre un board Miro avec quatre colonnes :
- Ce qui est bien
- Ce qu’on a appris
- Ce qui ne va pas
- Ce qu’on voudrait
Chacun ajoute des notes, en privé, en même temps. Écrire avant de parler, c’est toute l’astuce : ça évite que la voix la plus forte impose l’agenda et ça évite la pensée de groupe. Ensuite chacun reçoit un petit nombre de votes (on en utilise trois) à dépenser sur les sujets qu’il veut le plus discuter. On ne discute que des sujets les plus votés. Le reste est consigné, pas perdu.
Essayez le flux. Vous avez trois votes :
Ce qui est bien
Ce qu'on a appris
Ce qui ne va pas
Ce qu'on voudrait
- Rien encore. Votez pour ce qui compte le plus.
Vous avez 3 votes. Dépensez-les, puis on ne discute que du haut du classement.
La rétro, c’est là où toutes les autres cérémonies de cette page ont été réglées. C’est aussi la cérémonie la plus susceptible de devenir du théâtre. La façon la plus courante dont les rétros échouent n’est pas le format, c’est le suivi :
La raison pour laquelle la plupart des rétrospectives échouent n’est pas la réunion elle-même, c’est ce qui se passe (ou ne se passe pas) après. Les actions sont discutées, puis oubliées au sprint suivant.
Source : Easy Agile, Why Retrospectives Fail
C’est exactement là qu’on est le plus faible, donc je ne vais pas faire semblant du contraire. On discute des sujets du haut du classement et on les suit vaguement, mais on n’assigne pas de responsable nommé et on n’en fait pas un ticket Jira. Du coup, certains dérivent, et la même plainte resurgit quelques rétros plus tard. Le correctif qu’on sait devoir appliquer est ennuyeux : deux ou trois actions maximum, chacune avec un responsable et un ticket, revues au début de la rétro suivante. Une action sans responsable n’a pas vraiment eu lieu. On n’y est pas encore, et l’écrire ici, c’est un peu pour se forcer la main.
Planning poker : la taille est jetable
On dimensionne les tickets avec planITpoker, mais avec un choix délibéré : on ne vote pas en chiffres. On vote en tailles de t-shirt, XS, S, M, L, XL. Les chiffres invitent à une fausse précision (est-ce vraiment un 5 et pas un 8 ?) et, pire, ils invitent quelqu’un à les additionner en un chiffre de vélocité pour l’agiter. Les tailles résistent aux deux. “C’est un Large” lance une conversation. “C’est 8 points” lance un tableur.
Chacun vote en même temps, caché, puis on révèle ensemble. La révélation à l’aveugle est le point clé : elle tue l’ancrage, pour qu’un junior ne se contente pas de répéter la carte du senior.
Essayez. Choisissez une carte, puis révélez l’équipe :
Vous estimez "Ajouter l'export CSV par locataire". Choisissez votre carte.
Écart : S à XL. Personne n'a tort. Quelqu'un sait quelque chose que les autres ignorent.
La taille est jetable. La discussion que l'écart déclenche est le livrable.
Remarquez ce que montre le widget : un large écart, S à côté de XL. Ce n’est pas un échec de l’estimation, c’est l’estimation qui fait son travail. Quand les tailles divergent, quelqu’un sait quelque chose que les autres ignorent, une dépendance cachée, un cas limite, un locataire qui se comporte différemment. La conversation qui suit est le vrai livrable.
Je veux être juste envers les critiques ici, parce qu’ils sont la raison pour laquelle on a abandonné les chiffres. Il y a une contestation bruyante et crédible contre les story points :
Je n’aime pas les story points parce qu’ils donnent une fausse impression de précision, et dès que le management se met à les traiter comme une mesure de productivité, ils sont retournés comme une arme contre les développeurs mêmes qui les produisent.
Source : paraphrase de Tomasz Lakomy, Why I don’t like story-point-driven estimates, et Scott Logic, Story points are wasting time
Ils ont raison sur le mode d’échec. Les points deviennent du poison à l’instant où un manager en fait un tableau de scores. Les tailles de t-shirt sont notre défense : il n’y a rien à additionner, rien à mettre en graphique, rien à retourner en arme. La taille est jetable, la discussion est le livrable. On utilise le vote pour déclencher une conversation, puis on oublie généralement la lettre.
Le daily : de la coordination, pas un rapport de statut
Quinze minutes, à la même heure chaque jour, tout le monde en caméra. Voici à quoi il sert, et à quoi il ne sert pas.
Ce n’est pas un rapport de statut au lead. Les dailies que les gens détestent à juste titre sont ceux où chacun récite ses tâches de la veille à un manager qui les note. Si votre daily n’est que ça, ç’aurait dû être une mise à jour écrite en asynchrone, un message Slack. Les critiques ont raison là-dessus. Gardez le temps synchrone pour les blocages. C’est donc ce que chacun couvre vraiment : ce qui me bloque, et ce que je m’apprête à toucher, surtout si c’est du code partagé. Pas un récital des tickets de la veille.
Étant entièrement à distance, on a ressenti l’attrait des stand-ups écrits en asynchrone, et pour le pur statut ils seraient meilleurs. Mais on a gardé le daily en direct pour une chose qu’il fait bien : coordonner et faire remonter les blocages en temps réel. C’est là que “je m’apprête à toucher au code de facturation partagé” rencontre “attends, moi aussi”. Cette collision n’arrive pas dans un fil de discussion. Donc la règle est : garder ça court, ne pas résoudre les problèmes en réunion, emmener les approfondissements dans un aparté juste après.
Moins de dérive au fil de l’eau fait partie des gains, pas le plus gros mais bien réel : comme on se synchronise chaque matin, moins de gens commencent discrètement un travail au hasard, et chacun a une idée à peu près juste de ce qui est en train d’être pris. Le plus gros gain reste les collisions qu’on évite en disant à voix haute ce qu’on s’apprête à toucher.
La revue de sprint : de la visibilité partagée, pas une démo
Appelez-la revue de release dans notre cas, puisqu’on ne fait pas de sprints fixes. Le piège dans lequel tout le monde tombe, c’est de la traiter comme une démo : un défilé de chaque tâche, joué devant un public. Le nôtre n’a aucun public externe, pas de clients, juste les développeurs, le produit et le QA, et c’est justement pour ça qu’on peut l’optimiser pour la compréhension partagée plutôt que pour la performance. Le guide de Scrum lui-même s’oppose aussi au piège de la démo :
La revue de sprint n’est pas une démo. C’est une session de travail pour inspecter le résultat et décider quoi faire ensuite. Si c’est une présentation à sens unique, vous vous y prenez mal.
Source : Scrum.org, Sprint Review: Much More Than Just A Demo
Pour nous, la vraie valeur n’est pas la démo du tout, c’est la visibilité partagée. On fait parcourir à toute l’équipe interne ce qui part dans la prochaine release et ce qui attend derrière. Trois choses en découlent :
- Tout le monde apprend le produit entier. Comme on discute de beaucoup de tickets, y compris ceux qu’on ne prendra pas personnellement, plus de gens comprennent plus du système. Les nouveaux montent en puissance plus vite.
- Moins de PR coincées dans la file de revue. Quand chacun a déjà le contexte d’un changement, les revues sont rapides au lieu d’être de l’archéologie.
- On attrape les doublons et les collisions. Discuter des tickets ensemble, c’est le moment où quelqu’un dit “c’est la même chose que ce que j’ai fait le mois dernier” ou “ces deux-là vont entrer en conflit”.
On garde bien un créneau séparé pour de vraies démos : une session du vendredi à laquelle on s’inscrit pour montrer quelque chose qu’on a livré. Soyons honnêtes : c’est notre cérémonie la plus faible. Elle a tendance à traîner en longueur, peu de gens s’inscrivent, et la moitié du temps le travail intéressant n’est jamais montré. C’est la revue de visibilité ci-dessus qui justifie son existence. La démo, elle, cherche encore son format.
La vérité peu glorieuse sur pourquoi ça marche
Rien de tout ça n’est malin. Si la visibilité partagée bat une démo léchée, c’est parce que la démo optimise pour paraître productif aux yeux des gens de l’extérieur, tandis que la revue optimise pour que l’équipe sache réellement ce qui se passe. La première est du théâtre. La seconde est le but.
La vraie leçon
Aucune de ces cinq cérémonies n’est nouvelle. Vous les connaissez toutes. Ce qui vaut la peine d’être copié, ce ne sont pas les cérémonies, c’est que chacune a été introduite pour corriger une douleur précise et nommée :
- Des bugs en prod → critères d’acceptation et rayon d’impact dans le ticket.
- Le chaos au fil de l’eau → le daily comme coordination.
- Des estimations que personne ne croyait → planning poker à l’aveugle en tailles de t-shirt, avec la taille jetée après.
- Aucune vision partagée → la revue comme visibilité, pas comme démo.
- Tout qui dérive → la rétro, avec des actions qui ont un responsable.
On ne fait pas du Scrum de manuel. Pas de sprints fixes, pas de Three Amigos formels, et un écart honnête où les auteurs s’auto-certifient encore leurs propres releases. C’est très bien. Le but n’a jamais été de mener les cérémonies correctement. C’était d’arrêter de livrer des bugs et de commencer à savoir ce que fait l’équipe. Choisissez la douleur que vous avez vraiment, et ajoutez la seule cérémonie qui la vise. Puis menez la rétro, et laissez-la vous dire quoi ajouter ensuite.