Comme tout le monde, j’ai parfois envie de me frapper. Pas méchamment. Pas trop violemment non plus. Mais j’ai parfois envie de me frapper. Le plus souvent le front avec ma paume. Un peu comme ce bon vieux Capitaine Picard. 

Parfois, c’est parce que j’ai (re)fait une erreur. Mais c’est souvent quand on me fait me rendre compte de quelque chose où – a posteriori – je me dis que j’aurais dû le voir tout seul. « BON SANG, MAIS C’EST BIEN SÛR ! »

Dans le cas qui nous intéresse, c’est une conférence qui m’a aidé à ouvrir les yeux sur un sujet que j’entrevoyais sans le voir dans sa globalité. Cette, conférence, c’est « Fighting the invisible enemy » de Paul Rayner.

Qu’est-ce que la productivité ?

Une des problématiques majeures de toute organisation est d’optimiser sa productivité. C’est d’autant plus vrai dans notre domaine du développement logiciel, où nous ne produisons jamais assez vite. On nous demande répondre à un besoin utilisateur le plus rapidement possible en production. Mais comment le mesurer ? On apprend en cours de science économique et sociale au lycée que la productivité est le résultat de la formule suivante :

productivité = production / quantité de travail

La quantité de travail peut être du temps, et l’on parlera de productivité horaire ou des humains (s’il vous plait, ne parlez pas de ressources), l’on parlera dans ce cas de productivité par tête.

La productivité étant un ratio, il y a donc deux façons d’optimiser la productivité. Soit on vise à augmenter la quantité produite à quantité de travail égale, soit on vise à diminuer la quantité de travail tout en produisant autant. C’est sur ce deuxième axe que nous nous acharnons en permanence : nous automatisons les tâches récurrentes, nous simplifions nos process autant que possible. Bref, nous essayons d’aller plus vite. Mais attention aux effets pervers. Si on pousse la logique au bout et qu’on automatise toutes les tâches récurrentes, il ne restera que des tâches complexes, et donc intellectuellement exigeantes. Et logiquement :

  • Tout cerveau a ses limites. Attention à ne pas épuiser psychologiquement les pauvres humains accompagnant lesdits cerveaux.
  • Cynefin nous dit – et c’est logique – que les tâches complexes sont par essence plus difficiles à estimer. Donc mécaniquement, plus on délègue les tâches simples à la machine, moins les équipes sont prédictibles. (J’en parlais un peu dans cet article).

Loin de moi l’idée de militer contre l’automatisation, mais autant anticiper ses effets de bord potentiels. Personnellement, mes solutions préférées sont de laisser du temps aux développeurs pour travailler sur d’autres sujets que leurs projets principaux et de ne pas charger les développeurs à 100% pour leur laisser la possibilité de lever la tête du guidon, améliorer leurs propres conditions de travail et travailler sur la dette technique. Peu de métiers ont autant la main sur leur poste de travail et la façon dont ils travaillent, autant en profiter.

Pour en revenir à notre sujet, le gros souci avec cette méthode de calcul de la productivité est sa vision statique de la production. Cela fonctionne dans des environnements où la production est stable, ou a minima prédictible. Et si c’était le cas dans notre domaine, on le saurait depuis longtemps. Donc essayons de réfléchir différemment. Par le passé, plusieurs méthodologies ont basé leur vision du travail (collaboratif ou non) sous forme de flux. On pense évidemment au Toyota Production System, dont émergera le Lean Manufacturing dont les héritiers côté logiciel sont le Lean Software Development et Kanban.  Un des axes fondateurs de toutes ces méthodologies est la réduction du gâchis (« waste »).

Les files d’attente

Don Reinertsen – dont Paul Rayner tire une bonne partie de ses enseignements – a une opinion assez tranchée sur le sujet :

The enemy of flow is the invisible and unmeasured queues that undermine all aspects of product development performance.

Donc les ennemis sont les files d’attente. Mais pas toutes : les files d’attente invisibles et non-mesurées. D’autant plus qu’elles deviennent rapidement hors de contrôle. Pour illustrer son propos, Paul Rayner prend l’exemple d’un flux de travail standard, allant de l’émergence d’une idée à l’utilisation d’une fonctionnalité d’une application quelconque en production. Le board de mon équipe ressemble à ceci :

C’est assez long, mais nous avons pris le parti de modéliser l’intégralité du processus pour aligner l’ensemble des partis prenantes et identifier les goulots d’étranglement. Les seules particularités nous concernant sont éventuellement :

  • l’obligation d’une revue de code au plus tard au moment de la pull request
  • le déploiement est décorrélé de l’activation en production grâce à des feature toggles.

Ensuite, nous ajoutons les responsabilités en face de chaque étape.

Nous voyons que nous avons 4 personnes minimum dans l’équipe : un PO, un QA, un développeur et un autre développeur pour relire le code du premier. Regardons maintenant les étapes où les rôles changent :

C’est souvent à ces étapes que les tâches s’accumulent. Il n’y a pas de mystère, chaque changement de rôle cache une file d’attente. Un board Kanban est simplement une manière de mettre en valeur ces files d’attente.

Les boards Kanban sont une chose, mais les outils sont généralement peu adaptés à l’analyse des goulots d’étranglement. Nous utilisons VSTS. Et il faut un peu fouiller pour trouver l’historique d’une user story :

Ça nous mène à un écran qui a cette tête :

On notera plusieurs choses ici :

  • Nous n’avons pas modélisé dans VSTS notre flux visible sur le board physique. C’est déjà un problème en tant que tel. Nous manquerons de données pour analyser notre activité.
  • Toutes les activités et dates sont bien présentes dans VSTS… mais la visualisation est axée sur les transitions d’état et pas sur les attentes.

Si on regarde de plus près, on notera que cette user story aura attendu 14 jours avant d’être engagée, pour seulement 8 jours pour être développée, testée et déployée en production. On peut logiquement se demander s’il n’y a pas une file d’attente cachée derrière. La chose à retenir ici est qu’il nous faut un moyen pour mettre en valeur ces files d’attente. Or toutes les méthodologies de travail modernes (et donc agiles) mettent l’accent sur la structure et l’organisation du travail. Mais dans quel but ? Le but devrait être un flux de travail efficace. L’organisation n’est qu’un moyen d’y parvenir. Mais pas un but en soi.

Parkings et autoroutes

Paul Rayner utilise une autre analogie intéressante. Dans énormément d’équipes, on raisonne comme si la capacité de production – qu’on l’appelle vélocité ou qu’on parle en jours-homme – était un réceptacle. « Mon équipe abat tant de points par sprint, nous allons donc remplir ce réceptacle le plus possible pour utiliser au mieux ses capacités ». Ne devrions-nous pas nous demander de quelle façon nous assurer que le flux, du besoin en entrée à un logiciel en sortie, est le plus rapide et le plus fluide ?

En effet, le flux est une notion dynamique, tandis la capacité de production est statique. Il convient donc de voir le problème sous un angle différent. Rayner nous incite à ne pas voir son équipe comme un parking, mais plutôt comme une autoroute. Et là, on commence à voir des choses intéressantes. Par exemple, l’A6 entre Paris et Lyon est ouverte tous les jours de l’année. Mais selon que vous fassiez la route une nuit du lundi au mardi en novembre ou le vendredi 18h de week-end du 15 août, il est possible que le ressenti des passagers soit sensiblement différent.

A noter que si l’on envisage la capacité de travail comme un flux dynamique, il faudra nécessairement adapter la façon dont on travaille en termes d’estimation, planification, exécution des tâches et suivi.

En observant l’immense majorité des équipes, on arrive au constat qu’elles se trouvent dans un état de congestion permanente. Comme si vous étiez coincés dans les bouchons et qu’on vous appelait pour vous rappeler que vous deviez arriver à 19h pour prendre l’apéro chez belle-maman. Donc demandons-nous plutôt ce qu’on peut faire pour rendre plus fluide un système dans son ensemble. Et comme toujours, des gens bien plus intelligents que nous (ou que moi, en tout cas) se sont penchés sur ces questions.

Congestion

Dan Slimmon en parlait dans cet article (et aussi dans celui-ci) en 2015 : les tentatives d’optimisation des ressources peuvent générer précisément l’inverse du résultat recherché. Si le processeur de votre PC tourne fréquemment à 100%, ce n’est PAS une bonne chose. Concernant le trafic autoroutier, il a été constaté qu’il suit la bonne vieille loi binomiale :

Le débit (« throughput ») décroît passé une certaine vitesse. Plusieurs facteurs viennent expliquer cette constatation. En effet, plus la vitesse est élevée, plus les distances de sécurité doivent être grandes, réduisant la densité de véhicules. Et surtout, plus la tolérance aux aléas diminue. A 50km/h, vous vous déportez sans trop de soucis pour éviter cet élan qui traverse le périphérique (ça arrive tous les jours à Paris). A 150km/h, c’est un peu plus compliqué. C’est l’accident, une voie neutralisée, les bouchons, les sauvages qui roulent sur la bande d’arrêt d’urgence, les zombies, la fin de la civilisation, de la vie sur terre et des cacahuètes en général. L’optimal, quant à lui, se situe entre 50 et 60%.

Les modèles mentaux sont essentiels quand on travaille dans un domaine complexe. Il convient de bien les choisir.

Si votre équipe est un parking, votre but est de maximiser son remplissage.

Si votre équipe est une autoroute, votre but est de réduire la congestion.

Ces deux modèles mentaux ne sont pas seulement différents. Ils sont radicalement opposés. Et il est tout à fait possible, voire probable, que votre équipe gagne en efficacité en réduisant le nombre de user stories que vous planifiez dans un sprint. C’est sans doute compliqué à entendre. C’est sans doute compliqué à expliquer à un product owner ou au management. Mais analysez bien les effets pervers engendrés dans ces équipes qui n’ont que le time to market à la bouche et qui n’ont jamais le temps de bien faire leur travail.

Caractéristiques des files d’attente

Elles sont émergentes

Une file d’attente n’est pas un état. Elle est la conséquence d’un événement. Un bon exemple est donné sur le Github de iamfranco :

Dans cet exemple, nous prenons un système dense, mais qui fonctionne bien. Puis nous introduisons un ralentissement. Rien d’incroyable : quelques dizièmes de secondes, puis retour à la normale. Dès que vous introduisez une congestion dans un système, à densité égale, elle ne disparaît jamais.

Elles sont inévitables

Dans un système dynamique, les choses changent. Les problèmes surviennent, les gens partent en vacances, les contextes évoluent. Donc les files d’attente émergeront mécaniquement. La vraie question est de savoir comment réagit ce système à la congestion. Quelle est sa résilience ?

Dans le monde merveilleux du développement logiciel, l’équivalent d’une voie neutralisée ou d’un changement de fil peut être d’attendre qu’un tel soit disponible, de changer de contexte entre différentes tâches, etc. Tous ces épiphénomènes ont des effets de bord plus ou moins profonds sur le fonctionnement global du système.

Elles augmentent votre temps de cycle de façon non-linéaire

Le temps de cycle est le temps qu’il faut pour emmener une user story de l’émergence du besoin à l’utilisation d’une nouvelle fonctionnalité en production.

Selon le taux d’utilisation de la capacité, le système se comporte différemment dans le cas où un événement générant une attente dans une file survient. Si la seule tâche de votre journée est de passer à la Poste chercher un colis, vous pouvez vous permettre d’attendre 20mn avant qu’on vous le donne. En revanche, si vous avez 1h de pause le midi et qu’il vous faut déjà 25mn pour vous rendre à la Poste, ces 20mn d’attente sont plus problématiques. Surtout si ce colis contient vos clés de voiture pour partir en vacances ce soir.

L’idée ici est que si votre système est proche de sa capacité maximale (au-delà des 75%), le moindre grain de sable peut générer des effets dévastateurs. Alors qu’un système moins chargé sera bien plus tolérant aux aléas.

Elles se remplissent plus rapidement qu’elles ne se vident

Quand une équipe se retrouve dans un état de congestion, son premier réflexe (outre planquer le problème sous le tapis) (ne faites pas ça) est de se débarrasser au plus tôt du problème. Quitte à le faire un peu violemment, et éventuellement de filer le bébé à l’équipe suivante, qui devient elle-même congestionnée. On aura peut-être soulagé localement une partie du système, mais l’ensemble peut rester en souffrance.

Elles sont un indicateur majeur des temps de cycle longs et du débit réduit

Quand les équipes s’affairent le plus souvent à réfléchir comment améliorer leur vélocité, peut-être qu’elles devraient plutôt chercher à réduire leurs temps d’attente. Toujours d’après Reinertsen,

Les files d’attente sont la source de la majorité du gâchis dans le développement de produits.

Et dès qu’on parle de gâchis, on lie le développement de logiciels à sa dimension économique, ce dont on parle rarement. Et pourtant, le coût du logiciel dans une entreprise est considérable. Parfois colossal.

Remèdes de grand-mère contre les vilaines files d’attente

Maintenant qu’on a identifié les files d’attente comme étant les enfants illégitimes de Satan, comment fait-on ? On pourrait bien être tentés de les interdire au nom de la Convention de Genève, sauf qu’on a dit qu’elles étaient émergentes et inévitables. Il faudra donc s’en accommoder. Et dans ce cas, il faudra les surveiller et les circonscrire afin de garder le contrôle. Quelles techniques peut-on adopter pour cela ?

  • Réduire la taille des lots : les agilistes l’ont compris depuis longtemps. C’est plus facile de faire écouler du sable que des gros cailloux.
  • Engager des actions significatives quand les files commencent à s’engorger. Cela nécessite de définir des seuils. C’est vraiment ces actions qui sont la clé de la bonne gestion des seuils. La surveillance et la détection de passage de seuils n’ont pas la moindre valeur sans les actions qui doivent en découler.

Voici enfin 9 types d’actions possibles quand une file d’attente émerge :

  1. N’engagez pas de nouvelles user stories. Ne faites pas de fausses promesses.
  2. Purgez la file d’attente des éléments à faible valeur ajoutée. Si l’effort à produire une user story est plus élevée que ce qu’elle va apporter, son ROI est négatif.
  3. Réduisez les user stories au strict nécessaire. Il sera toujours temps de les améliorer dans un prochain incrément de produit.
  4. Accentuez l’effort sur la file d’attente. Si un ingénieur QA est en vacances et que votre colonne « à tester » s’engorge, demandez à d’autres membres de l’équipe de réaliser certains des tests.
  5. Demandez un coup de main ! Un renfort peut dans certains cas être salvateur. Tout comme il peut dégrader la situation, donc pesez bien le pour et le contre.
  6. Assurez-vous d’avoir des experts disponibles rapidement, pour résoudre un problème. Soit en leur laissant du temps disponible, ou a minima qu’ils soient en capacité de se rendre disponibles.
  7. En contrepartie, assurez-vous d’avoir aussi un certain nombre de couteaux suisses. Des gens capables d’intervenir sur une gamme large de sujets. Trouver le bon équilibre entre les experts et les couteaux suisses n’est pas simple, mais ça peut vous simplifier la vie.
  8. A chaque fois que vous avez un changement de rôle dans votre processus (quand la user story passe de « en cours de développement » à « à tester » par exemple), assurez-vous d’avoir des zones de recoupement. Si le développeur a des notions de test et que le testeur sait lire, voire écrire du code, vous rendez cette zone moins imperméable et donc le passage moins risqué et plus fluide. Le rapprochement du métier et des développeurs prôné par l’agilité, le BDD et DevOps sont des émanations de ce principe.
  9. Adaptez la priorisation de votre backlog à la capacité disponible pour chacun des rôles à cet instant. Si vous engagez une user story nécessitant de fortes compétences en infrastructure alors que les experts DevOps sont déjà accaparés, vous engorgez une file d’attente.

Attention, l’ensemble des points précédents sont complémentaires. Un abus de l’un peut entraîner une violation d’un autre. Tout est question d’équilibre, ici.

Voilà globalement ce que j’ai retenu de ce talk bien dense mais vraiment captivant. Je vous invite évidemment à le regarder ici :

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *