Vous et votre équipe travaillez sur un projet et votre gestionnaire arrive avec un calendrier de livraison strict. En tant qu’équipe, vous aimez les défis et donc vous embarquez dans les plans de votre gestionnaire. Le développement est effréné, mais vous progressez. Plus vous vous approchez de la date de livraison, plus vous vous rendez compte que vous n’y arriverez pas. Et votre gestionnaire s’en rend compte aussi ! Il vous demande donc de trouver des façons de livrer plus rapidement votre travail. Quel en sera le prix ?
Le désir de livrer le plus rapidement possible a d’énormes impacts sur le produit développé. Que ce soit le stress accumulé par les membres de l’équipe ou encore les sacrifices consentis sur la qualité du travail, communément appelés la dette technique, il est rare que les bénéfices d’une livraison rapide soient supérieurs aux dommages que cette pratique peut causer.
Dans de telles circonstances, comment pouvons-nous repenser notre approche pour concilier le besoin de rapidité avec l’exigence de qualité sans compromettre le produit final ? Quelles stratégies peuvent être mises en œuvre pour équilibrer ces objectifs et assurer la pérennité du produit et de l’équipe ?
Changer son vocabulaire
Je mentionne dans mon exemple la nécessité de « livrer rapidement ». Cependant, ce n’est pas la bonne expression. Le terme « rapide » peut souvent être associé à un sentiment d’urgence. Un sentiment qui nous fait dire : « Je dois me dépêcher, sinon je n’y arriverai pas ! ». Lorsqu’une personne est dans cette mentalité, tout aspect de qualité dans son travail devient secondaire. Cela s’explique par la peur des conséquences. « Qu’est-ce qui va m’arriver si je ne livre pas à temps ? Est-ce qu’on va me crier dessus ? Est-ce que ça va mettre mon emploi en danger ? ».
Qu’est-ce qu’on a tendance à observer lorsque ça arrive ? On commence à voir du travail bâclé ! Il est facile pour les gens de tourner les coins ronds pour atteindre leur objectif. Bien que ça leur permette de gagner en vélocité dans l’immédiat, ce n’est qu’une illusion. Mal faire notre travail en informatique introduit le concept de dette technique.
« La dette technique désigne ce qui se produit lorsque les équipes de développement prennent des mesures pour accélérer la livraison d’un élément de fonctionnalité ou d’un projet qui doit ensuite être retravaillé. En d’autres termes, la dette technique est le résultat d’une priorité donnée à la rapidité de livraison plutôt qu’à la perfection du code. »
Alors, est-ce qu’on souhaite réellement « livrer rapidement » ? Généralement, cette attitude est à proscrire dans une équipe de développement, car elle nuit au développement global de l’application sur le court, moyen et long terme. Avec ces quelques mots, il est possible d’instaurer des sentiments négatifs ainsi que des réactions indésirables. Dans ce cas, qu’est-ce qui serait plus approprié de dire lorsque l’on veut être efficace dans la réalisation de notre travail ?
L’expression que je préconise est de vouloir livrer plus tôt. Comparativement au terme « rapide », le concept de « plus tôt » a une connotation beaucoup moins négative dans le contexte de livraison. Les questions passent de « Qu’est-ce que je peux couper pour livrer rapidement ? » à « Comment je pourrais optimiser mon processus pour livrer plus tôt ? ». C’est le genre de question à se poser lorsque l’on désire accélérer le développement sans pour autant sacrifier la qualité.
Bien sûr, il est possible de livrer plus tôt en tournant les coins ronds ! Cependant, je trouve que cette façon de parler ouvre la porte à d’autres solutions plus facilement que de parler de rapidité. Donc, comment pouvons-nous, lors du développement de produit, livrer plus tôt les nouvelles fonctionnalités ?
Identifier les sources de ralentissement
Parmi les principales sources de ralentissement dans le développement logiciel, on retrouve les temps morts ! Certains diront qu’ils sont constamment en train de programmer de nouvelles fonctionnalités, donc il n’y a pas de temps mort dans leur travail. C’est là où ces personnes se trompent ! En effet, lorsqu’on parle de temps d’attente, on ne parle pas de membres de l’équipe qui se tournent les pouces, mais plutôt de tâches qui restent inactives durant de longues périodes sans que personne ne travaille dessus.
Prenons un exemple tiré d’une conférence de Dragan Stepanović sur les dangers du travail asynchrone.
Source : Async Code Reviews Are Killing Your Company’s Throughput, Dragan Stepanović, NDC Copenhague, 2022.
Dans cet exemple, Emma travaille sur la tâche 1 et demande ensuite à Lucas de faire une revue de code. C’est à partir de ce moment que les temps morts commencent. Après un long moment, Lucas prend finalement le temps de passer en revue la tâche et demande des changements à Emma. Pendant qu’elle attendait, Emma a décidé de commencer une deuxième tâche. Il y a maintenant trois tâches en développement en parallèle : deux pour Emma et une pour Lucas. Si l’on ignore le temps qui n’est pas réservé au développement (dîner, temps en dehors des heures de travail, etc.), il y aura toujours au minimum une tâche qui accumule du temps mort. Dans l’exemple d’Emma et Lucas, on se retrouve avec la tâche 1 qui a passé plus de temps à attendre que de temps en développement !
Chaque nouvelle tâche en parallèle va d’ailleurs augmenter le temps d’attente des autres tâches. Dans l’objectif de livrer les tâches le plus tôt possible, une solution serait donc de diminuer au maximum les temps morts de nos tâches. Cette piste d’amélioration nous permet de gagner en efficacité sans sacrifier la qualité.
Conseil : Si vous avez plusieurs tâches encore en cours à la fin de chaque itération de développement (sprint), il est fort probable que les membres de votre équipe travaillent en silo et qu’il y a beaucoup de temps mort sur les tâches.
Diagnostiquer les temps morts
Lors du développement d’une fonctionnalité, le délai de changement (lead time) d’une tâche peut être divisé en quatre grandes catégories :
-
La programmation : C’est le temps passé par le développeur ou la développeuse pour coder la fonctionnalité.
-
La prise en charge : Lorsque le développement est complété, c’est le temps d’attente avant qu’une revue de code ne commence. Cette étape est considérée comme du temps mort.
-
La revue : C’est le temps passé à examiner le code par une autre personne, ainsi que le temps pour appliquer des changements s’il y en a. Cette étape se termine lorsque le code est fusionné à la branche principale.
-
Le déploiement : Une fois le code fusionné à la branche principale, c’est le temps d’attente avant que ce code soit déployé en ligne.
Dans l’exemple de Dragan avec Emma et Lucas, deux de ces catégories contiennent beaucoup de temps mort : le temps de prise en charge et la revue de code.
Trouver des pistes de solution
Maintenant que nous avons ciblé une source de ralentissement dans la réalisation de nos tâches, que pouvons-nous faire concrètement pour les livrer plus tôt ?
Réviser le code plus tôt
Effectuer une revue de code peut demander beaucoup de « jus de cerveau ». En effet, il y a beaucoup de choses à prendre en compte en lisant le code :
- Est-ce que le code est lisible ?
- Est-ce que l’architecture fait sens ?
- Est-ce que les critères d’acceptation sont respectés ?
- Est-ce que les tests sont présents ?
- Y a-t-il des cas non gérés ?
Certains de ces points peuvent causer des problèmes s’ils ne sont pas respectés. Par exemple, les changements que vous avez apportés au système peuvent briser une autre fonctionnalité parce qu’elles passent par le même code. Ce type d’erreur nécessite de revenir en arrière et de revoir l’implémentation. Pour éviter ce type de ralentissement, effectuer une revue de code plus tôt dans le développement permettrait d’éviter le travail en double. Par exemple, il est possible de concevoir un plan d’architecture sur la façon dont on envisage d’implémenter la fonctionnalité et le faire valider par ses pairs avant de l’implémenter.
Communiquer
Comment informez-vous vos collègues qu’une tâche est prête à passer en revue ? L’efficacité des moyens de communication d’une équipe a un impact direct sur la durée de prise en charge des revues de code. Selon votre méthode de travail en équipe, il existe plusieurs façons d’informer vos collègues qu’une tâche est prête à passer en revue. Par exemple, une équipe hautement collaborative peut simplement le mentionner à l’équipe de façon synchrone à l’aide d’outils de canaux vocaux, comme Discord ou Teams. Pour les équipes un peu plus asynchrones, par exemple en raison de multiples fuseaux horaires, un robot envoyant automatiquement un message lorsqu’une nouvelle demande de fusion est prête pourrait être une solution. L’important pour minimiser les temps morts, c’est d’être efficace dans sa façon de communiquer l’état des tâches.
Réviser en binôme
Lors d’une revue de code, les discussions asynchrones sont responsables de la majorité du temps mort. Lorsque vous ne vous entendez pas sur un élément de la revue, le va-et-vient lors de la discussion peut grandement prolonger la durée de vie de la tâche. Une solution à cette source de ralentissement serait de faire une revue en binôme. Cela permet d’avoir des discussions en temps réel au besoin, et il arrive même que des points soient discutés qui auraient autrement été laissés de côté en raison de leur complexité. La revue en binôme favorise grandement le partage de connaissances entre les membres de l’équipe, en plus de permettre de compléter une tâche plus tôt.
Faire de petites demandes de fusion
Lorsque je demande à des développeurs ou des développeuses ce qui les démotive à faire des revues de code, la majorité des réponses tournent autour de la taille de celle-ci. Lorsqu’une demande de fusion est grande, il est difficile de réaliser une revue de qualité. Cela engendre trop d’informations à absorber et à comprendre en même temps, rendant difficile l’évaluation du code dans son ensemble.
Les équipes qui ont l’habitude de faire de grandes demandes de fusion (merge requests) vont généralement avoir un temps de prise en charge plus élevé, car les développeurs savent que cela va leur demander beaucoup de temps et d’efforts cognitifs. Il y a tellement de changements qu’il est difficile de bien maîtriser tout ce qu’il y a à passer en revue.
Les petites demandes de fusion sont beaucoup plus faciles à comprendre, à suivre et donc à évaluer, car la portée de la revue est limitée. De plus, le changement de contexte peut être très difficile dans notre travail. Il est donc compréhensible de ne pas vouloir interrompre sa concentration pour aller faire une revue du code de quelqu’un d’autre. Cependant, travailler par petites itérations signifie avoir des changements de contexte plus fréquents, mais plus naturels.
Conseil : Qui dit revues de code plus petites dit plus de revues de code à examiner. Effectivement, cette façon de faire crée plus de revues individuelles. Cette approche mettra au défi vos processus de revue de code et d’intégration en continu. En contrepartie, vous aurez du code prêt à livrer plus tôt et en plus petits incréments.
Découper le travail plus petit
Dans le point précédent, je mentionne de faire de plus petites revues de code pour qu’elles soient plus efficaces. Tout de même, il peut sembler contre-intuitif de livrer une partie de code qui n’apporte rien au produit par elle-même. Dans ce cas, une solution consiste à découper le travail en petits incréments de façon à apporter constamment de la valeur au produit. Cette approche s’appuie sur les solutions précédentes, mais d’un point de vue d’affaires, pour vos clients ou vos utilisateurs.
Martin Nadeau, gestionnaire de l’ingénierie sénior chez Nexapp, explique comment découper votre travail dans un article à ce sujet.
Adopter le « pair programming »
Dans la conférence mentionnée plus haut, Dragan Stepanović explique l’impact des petites revues de code sur l’efficacité d’une équipe à livrer de manière continue. Il souligne que la vitesse d’une revue de code est inversement proportionnelle à sa taille. Si l’on pousse ce concept à sa limite, quelle taille de revue de code serait la plus rapide à passer en revue ? Une revue d’une seule ligne ! Ainsi, la revue se fait lors du développement.
Le « pair programming » (programmation en binôme) est une méthode permettant de réaliser la revue de code en même temps que le développement. De plus, toute discussion sur l’architecture qui pourrait survenir pendant une revue de code se fait maintenant pendant le développement. Cela évite qu’une personne implémente une solution, puis doive appliquer de gros changements lors de la revue en réponse aux commentaires des pairs. Moins de retour sur le travail réalisé = moins de travail inutile = gain en efficacité.
Et le « shift-left » dans tout ça ?
Le principe du « shift-left » consiste à amener certaines étapes du processus plus tôt dans le développement. Si l’on regarde un tableau de projet Agile composé de plusieurs colonnes pour les différentes étapes, le « shift-left » revient à déplacer la responsabilité de certaines colonnes vers celles situées plus à gauche. Par exemple, pour les étapes se concentrant davantage sur la programmation d’une tâche, le « shift-left » pourrait impliquer de déplacer l’étape de revue de code dans l’étape de programmation (en cours).
Plusieurs des solutions mentionnées précédemment illustrent l’application du « shift-left » dans le développement. Amener les revues de code plus tôt permet de réduire les temps morts et d’éliminer du code qui n’aurait jamais passé les étapes suivantes du processus. Que ce soit par la préparation d’un plan d’architecture ou par le « pair programming » pour avoir une revue de code en temps réel, ces pratiques permettent de livrer le travail réalisé plus tôt et ainsi d’obtenir des retours des utilisateurs plus rapidement. Cela permet d’être proactif, d’optimiser le processus de développement et de transformer la manière dont les membres de l’équipe collaborent.
Les articles en vedette
Retour d’expérience sur un processus d’autosélection d’équipes
5 pièges courants qui réduisent l’efficacité de votre ingénierie logicielle
Shift-left sur le QA : une nouvelle approche de l’assurance qualité
Soyez les premiers au courant des derniers articles publiés
Abonnez-vous à l’infolettre pour ne jamais rater une nouvelle publication de notre blogue et toutes nos nouvelles.