Easy Tech #28 - utiliser la puissance du lean pour l'adapter à l'informatique
La force du lean software development
Salut à tous,
Je reviens vous faire coucou après une petite pause sur le mois de décembre et sur début janvier. Ça m’a fait du bien de me reposer un petit peu et de réfléchir à comment faire évoluer cette newsletter. Je vous en dirai plus dans l’édition suivante.
En tout cas, cette édition compte pour moi car il s’agit de vous parler d’un livre que j’ai beaucoup aimé et qui a changé plein de choses dans ma manière de voir la tech.
Cette édition est un peu longue. Donc n’hésitez pas à la lire en plusieurs fois. Elle est structurée de la manière suivante :
Rappel sur l’histoire du lean software development, la théorie à laquelle cet ouvrage appartient
Les grands chapitres de ce livre Don Reinertsen à savoir :
1️⃣ La vue économique
2️⃣ Les files d’attente
3️⃣ La variabilité
4️⃣ La taille des batch (batch size)
5️⃣ Les contraintes sur le travail en cours (WIP)
6️⃣ L’optimisation du flux dans l’incertitude
7️⃣ Le feedback rapide
8️⃣ La décentralisation du contrôle
Histoire du lean software development
Le lean
Pour une brève histoire du Lean je te renvoie à mon édition sur le DevOps dans laquelle j’étais revenu sur cette notion.
En quelques mots :
→ Le lean est une discipline apparue dans les usines de Toyota après la Seconde Guerre Mondiale
→ Elle s’est distinguée par son efficacité et son côté humain, disruptif par rapport aux approches anciennes comme le Taylorisme
→ À tel point que le lean s’est vu appliquer à d’autres domaines que l’industrie lourde comme les organisations et également la tech.
Le lean appliqué à la tech
En matière d’application du lean à la tech, on peut identifier deux grands courants :
→ Le lean software development (LSD) : poussé par Mary Poppendieck
→ Le lean product development (LPD) : poussé par Don Reinertsen
Aujourd’hui, je dirais que le LSD est plus connu dans les sphères informatiques. Il a fait l’objet de plusieurs ouvrages. Et je dirais qu’il se distingue par une volonté très rigoureuse de prendre les principes du lean pour les transposer dans la tech.
Si ça vous intéresse, j’avais résumé l’ouvrage référence sur le sujet dans ce carrousel LinkedIn.
Je ne connais pas d’autres livres sur le LPD que l’ouvrage de Don Reinertsen Principles of Product Development Flow (PPDF) que cette newsletter résume. Cette variante est un peu moins connu que le LSD. Pour autant, elle a été remise au goût du jour (indirectement) par SAFe ! En effet le fameux framework d’agile à l’échelle s’est énormément inspiré du livre de Reinertsen pour définir ses fondamentaux.
Ci-dessous, vous voyez les grands principes structurants de SAFe. #1, #3, #6, #7 et #9 sont directement tirés de PPDF.
Pour la suite, on assimilera LPD / LSD et également “lean appliqué à la tech”.
Maintenant qu’on a vu de manière macro le lean product development, creusons un petit peu ces grands principes mis en avant par Don Reinertsen
Concept 1️⃣ - economics
Présentation du principe
Description
Pour Reinertsen, cela revient à être “obsédé” par l’argent. Ou plus précisément, à prendre les décisions à partir d’une quantification économique.
Pourquoi ?
Parce que c’est ce qui permet de prendre de meilleures décisions. Notamment cela nous ramène au coeur de notre travail : combien on a investi et combien ça rapporte au final.
Or ici, avec le LPD, on parle de mettre en place de nouveaux process et de nouvelles manières de bosser. Ça commence donc par se demander pourquoi on veut faire ça. On voudrait le faire pour améliorer la situation, pour faire plus de profits.
C’est donc une brique importante à avoir dans un premier temps.
Illustration
Le fait qu’on n’analyse pas suffisamment avec un prisme économique peut s’illustrer de 2 manières pour Reinertsen :
→ Les vanity metrics : ce sont des indicateurs qui boostent l’ego mais n’ont pas de lien avec la valeur qu’apporte le produit. Par exemple, une vanity metric pourrait être le nombre de visiteurs sur le site qui héberge un produit. Problème : ce n’est pas parce que les gens visitent que mon produit apporte de la valeur. Si je suis Amazon, j’apporte de la valeur lorsque les gens trouvent des produits qui leur conviennent. Donc quand ils achètent. Ne pas avoir un point de vue économique peut donc nous amener à vouloir maximiser le nombre de visiteurs sans aller plus loin. Ce qui nuirait au produit.
→ Les métriques “d’utilisation” dans la tech : pour Reinertsen, d’autres indicateurs très négatifs sont les indicateurs qui renvoient à “est-ce que l’équipe est occupée”. Typiquement, on va vouloir mesurer le “taux d’occupation” d’une équipe de développement. Un taux de 100% veut dire que l’équipe passe tout son temps à développer. Intéressant non ? Pas vraiment nous dit Reinertsen. Pour une raison simple : ce n’est pas parce que l’équipe bosse à fond, que ce qu’elle délivre apporte de la valeur, et donc, génère de l’argent pour l’entreprise. En plus, pousser à 100% les équipes fait que ça les démotive et les pousse au burn out. Donc même si elles bossaient sur les bons sujets, cela resterait un calcul perdant au niveau économique.
Mettre en pratique
→ Utiliser des modèles d’analyse qui incluent la dimension économique. C’est le modèle ou framework présenté ci-dessous. Pour Reinertsen, le choix de lancer ou non un développement doit donc dépendre de ces différents paramètres :
Development expense – the cost of labor and materials required to implement a capability
Lead time – the time needed to implement the capability (described as ‘Cycle time’ in Reinertsen’s work)
Product cost – the manufacturing cost (of goods sold) and deployment and operational costs
Value – the economic worth of the capability to the business and the customer
Risk – the uncertainty of the solution’s technical or business success
→ Créer des systèmes pour favoriser des décisions pas chères et rapides. C’est un autre constat fait par Reinertsen : beaucoup de bonnes décisions se périment. C’est à dire que parfois, une décision n’est bonne que lorsqu’elle est prise rapidement. Et en corollaire, il remarque que ces décisions sont aussi beaucoup moins chères en général.
On peut faire un mini parallèle avec la vague autour de l’IA. Il y a un an, ChatGPT venait juste d’être lancé. C’était sûrement le bon moment si on voulait devenir expert sur le sujet et lancer un business autour de ça. En tout cas aujourd’hui ce n’est plus du tout aussi pertinent, parce qu’il y a beaucoup plus de concurrence. Le fait de se lancer sur ce secteur est une décision qui se périmait.
Et de la même manière, se lancer il y a un an ne demandait pas non plus beaucoup d’argent. Au démarrage, quelques heures par semaine pouvaient suffire pour se dégager un avantage concurrentiel. La décision était également peu chère à ce moment. En revanche aujourd’hui, il faudrait sûrement beaucoup plus investir pour devenir expert.
Reinertsen invite donc à créer des systèmes au sein des organisations pour s’assurer que lorsqu’une nouvelle opportunité arrive, les décisions puissent être prises vite afin d’en profiter.
→ Raisonner en valeur relative et coût relatif. Il s’agit ici de se méfier des fameux coûts irrécupérables ! J’en avais parlé dans mon édition sur les biais. En 2 mots, lorsqu’on investit de l’argent pour créer un produit, cet argent déjà dépensé influence notre décision d’engager un nouveau développement sur celui-ci ou non. Pourtant, Reinertsen nous invite à être méfiant ! Ce n’est pas parce que j’ai déjà dépensé 10.000€ sur un produit, que cela doit influencer la décision de dépenser 1000€ de plus. Le seul paramètre qui devrait compter c’est : est-ce que ces 1000€ sont susceptibles de susciter un RoI suffisant ?
Concept 2️⃣ - queues (files d’attente)
Présentation du principe
Description
Les queues en anglais ou files d’attente en français correspondent bien à l’acception qu’on en a dans la vie de tous les jours. Il s’agit de situations où plusieurs éléments doivent être traités de manière linéaire / séquentielle.
→ Quand je fais la queue à la boulangerie : pour acheter mon pain, j’attends que les gens devant moi aient pu l’acheter avant
→ Quand je fais la queue aux portiques à l’aéroport : j’attends d’être dispatché sur un des portiques puis ensuite, j’attends d’avoir pu passer aux rayons X.
Pour Reinertsen, ces files d’attente existent aussi en informatique ! Mais à la place des personnes, il s’agit des actions à réaliser lors du développement d’un logiciel.
→ J’ai 3 items à développer pour finaliser une fonctionnalité : j’ai une file d’attente de 3 items.
→ J’ai 2 validations à récupérer pour déployer en production : j’ai une file d’attente de 2 validations.
→ J’ai 5 maquettes à construire avec mes designers avant de lancer un développement : j’ai une file d’attente de 5 maquettes.
Et je peux très bien avoir une file d’attente qui combine des items à développer, des validations à récupérer et des maquettes à construire.
Il y a beaucoup de théorie mathématique autour de la gestion des files d’attente. Je ne vais pas rentrer dans ce détail (mais si ça vous intéresse, allez lire le livre parce que Reinertsen passe plusieurs pages à expliquer les équations mathématiques sous-jacentes). La manière “classique” de traiter les files d’attente s’appelle FIFO (first-in first-out = premier arrivé premier servi) :
Dans mon exemple de la boulangerie, le traitement est FIFO : la personne qui est arrivée la première est servie la première, la personne qui est arrivée ensuite est servie après.
En fait un tel traitement n’est pas évident dans pas mal de situations.
À l’hôpital typiquement, ça aurait beaucoup plus de sens d’appliquer un ordre de traitement lié à la gravité de la pathologie. Si j’ai un rhume, c’est “normal” que j’attende plus longtemps qu’une personne qui fait un AVC, même si je suis arrivé avant elle.
Illustration
J’aime bien les deux exemples suivants pour illustrer les enjeux autour des files d’attente :
→ Les tickets qui restent trop longtemps dans le backlog. On a souvent tendance à traiter les tickets dans son backlog en mode FIFO. D’une part, on n’a pas envie de remettre en cause un ticket qu’on a inscrit et fait apparaître dedans. D’autre part, on n’a pas non plus envie de faire passer devant un autre ticket. Le problème c’est que (1) les tickets ont tendance à se périmer ! Parfois l’utilisateur a besoin d’une fonctionnalité à un moment, mais ce besoin va disparaître ensuite. (2) Il faut reprioriser en continu car il va y avoir des urgences. Cela arrive toujours. Donc le fait d’être premier de la liste pour un ticket n’est pas une justification en soi pour être développé avant un ticket plus prioritaire.
→ Les tickets dont le traitement est démarrés sans être fini. Il va s’agir par exemple de tickets pour lesquels on a besoin d’un input de quelqu’un d’autre dans l’organisation. Ce ticket va rester dans la file d’attente, tant qu’il n’est pas finalisé. Pour autant, personne n’agit dessus (ou en tout cas personne dans l’équipe de développement). De tels tickets sont problématiques parce qu’on met toujours du temps pour les faire atterrir. Ils ont tendance à faire grossir la file d’attente globale sans aider à la réduire.
Mettre en pratique
→ Réduire les files d’attente : ça revient à avoir un frigo avec pas trop de choses dedans. Sinon, il y a une file d’attente entre les aliments. Et fatalement les aliments qui restent longtemps dedans sont probablement les moins appétissants et je vais avoir envie d’en racheter d’autres avant de les manger… donc ils vont rester et être de moins en moins appétissants. Même chose pour les fonctionnalités dans un backlog, ces features dont on se dit qu’il faudrait quand même les faire parce qu’on les a mises dedans sans savoir pourquoi. Mieux vaut les enlever une fois pour toutes. Poubelle !
→ Casser les logiques FIFO : ça paraît en fait très logique. Le plus important c’est de prioriser par ce qui a de la valeur. Pas en fonction de ce qui est arrivé avant chronologiquement. Comme ça, si quelque chose d’urgent arrive à un moment, je n’ai aucun problème à déprioriser d’autres éléments pour travailler dessus. Attention, ça paraît très logique, mais souvent c’est une décision qui est difficile à prendre. Donc forcez-vous à ce que l’ancienneté dans un backlog ne soit pas un critère de choix.
→ Mettre en place des guichets / self service : vous vous disez peut-être “OK c’est bien beau de vouloir réduire les files d’attente mais malheureusement, c’est jamais de ma faute !” De fait, on l’a vu. Souvent, ces files naissent d’un service qui est un goulet d’étranglement. Les tickets s’accumulent et comme ce service est sous l’eau et qu’il a des demandes émanant de plusieurs services, il va traiter les dossiers en mode FIFO pour plus d’équité. Pour éviter ce genre de problèmes, je vous conseille de mettre en place (i) soit des guichets, donc des heures de permanence pendant lesquelles ce service est disponible pour répondre, sans logique de file d’attente ; (ii) soit du self-service, donc donner aux personnes qui ont le besoin, les outils pour y répondre elles-mêmes.
Concept 3️⃣ - variability
Présentation du principe
Description
Il faut d’abord définir ce qu’est la variabilité. En lean, il s’agit d’un point identifié comme un des grands “déchets” / sources d’inefficacité. Ça renvoie à :
des machines qui ne fonctionnent pas toujours de la même manière ;
des opérateurs qui n’agissent pas exactement pareil ;
des fournisseurs qui ne livrent pas les mêmes quantités de matière première.
Dans l’industrie lourde, c’est très handicapant. D’où la classification en tant que déchet par le lean.
Pour autant, dans la tech, c’est plus naturel et moins problématique :
Les tâches humaines sont beaucoup moins standardisées ! Deux développeurs ne vont en général pas avoir exactement les mêmes choses à faire même s’ils travaillent sur la même application ou le même type de tâche.
Les ordinateurs sur lesquels on travaille pour déployer nos logiciels peuvent réagir de manière différente en fonction des situations. Quand bien même on a essayé de tout sécuriser au max.
Reinertsen nous invite donc à ne pas faire la chasse à la variabilité. Ça n’est pas aussi problématique que dans l’industrie.
Illustration
Plus largement, Reinertsen voit aussi la variabilité comme un moyen de générer de l’information.
Comme deux développeurs ne bossent pas exactement pareil, leurs différences de comportement vont entraîner des conséquences différentes sur le code. Ces conséquences sont autant d’apprentissages que j’ai l’opportunité de faire.
Comme deux ordinateurs vont réagir de manière différente, je vais apprendre des choses supplémentaires qui me permettront de mieux anticiper dans le futur.
C’est important car en matière d’informatique, on ne peut pas tout anticiper ni tout prévoir. Alors, la seule manière d’avoir des convictions fiables, c’est d’observer le comportement des systèmes et de le documenter petit à petit.
Pour le comprendre, j’aime bien l’analogie avec les enfants. Quand les enfants sont petits, ils ne connaissent pas les règles de fonctionnement du monde. Ils sont trop jeunes. Alors ils doivent être curieux. Ils testent des choses. Ils observent et petit à petit, ils se construisent leurs propres règles pour comprendre le monde dans lequel on vit.
Pour les systèmes informatiques, c’est la même chose. On doit être curieux et essayer de tester des situations différentes afin de faire émerger petit à petit, empiriquement, des règles de fonctionnement précises. Évidemment, on connaît déjà certaines règles comme “si je mets de l’eau sur un ordinateur, ça va le casser”. Mais ça va nous permettre de construire petit à petit des règles pertinentes.
Si on prend l’exemple plus concret des fonctionnalités, la variabilité à leur niveau ne doit pas être minimisée ou maximisée. Il faut ramener les choses à une analyse économique. Des petites variations sur les fonctionnalités peuvent être pertinentes lorsqu’elles apportent plus de valeur. En revanche, elles peuvent également en apporter moins. Donc il faut bien mesurer les choses et inciter à aller innover lorsqu’on est sur un domaine où on sait qu’on a un potentiel de valeur à apporter.
Mettre en pratique
→ Introduire des mécanismes pour exploiter la variabilité : avec deux aspects principaux. (1) Faire des tests rapides de nouvelles fonctionnalités, par exemple avec des interrupteurs de fonctionnalités qui vont permettre d’allumer / d’éteindre une fonctionnalité donnée sans développement supplémentaire. De la sorte, on peut regarder la fonctionnalité qui est la plus pertinente et enlever l’autre version. (2) Collecter les données suivant l’usage du produit par les utilisateurs. C’est ce qui nous permet de trancher sur le fait que l’introduction de la variabilité, et une fonctionnalité donnée, ou une autre, est plus efficace et performante.
→ Cultiver une culture d'innovation : c’est important que tout le monde au sein de l’équipe soit positif et encouragé à faire de l’innovation et des expérimentations dans un cadre contrôlé. Si on reprend la comparaison avec l’industrie : évidemment, on n’a pas envie que des ouvriers à la chaîne innovent ou expérimentent… la force de la tech, c’est qu’on peut se le permettre sur nos systèmes. C’est donc crucial de bien mettre en place un environnement qui la valorise.
→ Mettre en place de l’expérimentation contrôlée : on a les mécanismes pour tester des choses (premier point) et on a une culture qui valorise ces tests (deuxième point). C’est pertinent de cadrer un peu les choses pour s’assurer que ces innovations et expérimentations ne partent pas dans tous les sens. Pour rationaliser un peu sans lourdeur excessive, on peut définir des templates simples :
💡 Template d’expérimentation
(i) description de l’expérience
(ii) problème métier qu’elle est censée résoudre
(iii) durée prévue pour l’expérimentation
(iv) indicateur suivi
(v) critère de succès
c’est-à-dire, à partir de quelle évolution de l’indicateur suivi (iv) pourra-t-on considérer que ça a marché ou que ça n’a pas marché.
Concept 4️⃣ - batch size
J’avais déjà parlé de ce concept sans le nommer dans un autre épisode de ma newsletter #23 - Quatre principes pour de meilleures décisions. Il s’agissait du principe 4 = plus c’est petit mieux c’est ! Quand je parlais de ce qui devait être petit, il s’agissait de ces batch sizes.
Présentation du principe
Les batch sizes renvoient à la quantité d’effort pour réaliser une action. Pour Reinertsen, il y a des effets non linéaires lorsqu’on augmente la quantité d’effort pour réaliser une action donnée. C’est-à-dire que si “on a les yeux plus gros que le ventre”, et donc qu’on veut en faire trop d’un coup, sans découper en sous-tâches, on a plus de chance d’échouer à réaliser cette action.
Martin Fowler met en avant deux éléments qui expliquent cette évolution dans cet article :
→ Premièrement, certaines tâches sont beaucoup plus faciles à effectuer lorsqu’on les découpe en petites sous-tâches. Imaginons par exemple que je doive déplacer une masse de 100 kilos entre deux points éloignés de 50 mètres. Je pourrais facilement porter 100 fois 1 kilo sur 50 mètres. Pourquoi pas 10 trajets de 10 kilos mais ça serait fatiguant. 2 trajets à porter 50 kilos devraient être possibles mais très difficile. En revanche, je serai bien incapable de porter 100 kilos d’un coup sur cette distance. La difficulté en fonction de la masse transportée par trajet n’augmente pas de manière linéaire !
→ Deuxièmement, des petites tâches et des petites actions permettent de générer plus de feedback, ce qui me permet d’ajuster petit à petit. En 100 trajets de 50 mètres, je vais sûrement me rendre compte d’une technique qui marche mieux qu’une autre. Ça va me permettre d’optimiser et d’être encore plus efficace. Si je ne fais qu’un seul trajet, je n’aurai pas ce recul.
Cet exemple est aussi intéressant parce qu’il montre également qu’il y a une limite au fait de faire des choses plus petites. Évidemment, ça ne serait pas optimal de porter 1 gramme 100.000 fois sur 50 mètres (1 kilogramme = 1000 grammes donc 100 kilos = 100.000 grammes). Comme on le voit sur le graphe ci-dessous, il y a une taille optimale. Et à partir d’un seuil, faire plus petit devient contre-productif.
Ce graphe est issu du site de SAFe mais Reinertsen présente également le même graphe dans son livre :
On voit bien que si la taille est vraiment vraiment trop petite, le coût augmente.
On voit également bien que si la taille est plus grande, alors le coût augmente également.
On peut se dire qu’il ne faut pas aller dans l’extrême inverse, et trop réduire la taille des batches. Cela dit, j’ai toujours vu empiriquement dans la tech, qu’on avait tendance à grossir trop la taille de batches. Inversement, on arrive à faire preuve de beaucoup plus de bon sens pour identifier un batch trop petit. C’est d’ailleurs notre tendance naturelle d’essayer de faire plusieurs choses d’un coup et donc de grouper (to batch en anglais) des actions.
Mettre en pratique
→ Au préalable, cela passe par garantir des conditions pour pouvoir délivrer de la manière la plus itérative et incrémentale possible. Donc 1️⃣ avoir une archi pour faire évoluer très vite des fonctionnalités ; 2️⃣ disposer de tests automatiques pour valider rapidement les fonctionnalités construites. Souvent on voudrait bien fonctionner en petit batch. Mais en pratique, un legacy nous empêche de réaliser ces actions.
→ Au niveau fonctionnel, réduire le plus possible la taille des morceaux de fonctionnalités construits. Petites US, petits dévs, petits tests, petits déploiements et on récupère le feedback de l’utilisateur. Puis on recommence, et ainsi de suite. Plus c’est réduit mieux c’est. Et si l’utilisateur n’est pas dispo pour donner son feedback ? Pas grave, au moins on a déployé et c’est sécurisé au niveau technique.
Concept 5️⃣ - WIP constraints
Présentation du principe
Description
Le WIP = work in progress, renvoie aux tâches ou aux fonctionnalités en cours de réalisation mais pas encore finis. On va voir que ce “travail en cours” peut avoir un impact significatif sur l’efficacité de nos développements.
Reinertsen identifie 2 éléments intéressants autour de cette notion spécifiques à la tech. Ça va nous aider à comprendre comment agir dessus :
1️⃣ On a moins tendance à prendre conscience de la quantité de WIP. En effet, à la différence de ce qui se passe dans l’industrie, si une fonctionnalité (un morceau de produit) n’est pas finalisée, elle ne va pas traîner par terre dans un atelier. On parle “d’inventaire” invisible parce que tout est dématérialisé. C’est un facteur qui fait qu’on a tendance à voir le WIP augmenter très vite car on ne visualise pas bien son augmentation.
2️⃣ Le WIP renvoie aussi à une difficulté à achever des tâches. C’est un peu le symptôme de “je commence plein de choses sans jamais finir”. Or c’est problématique, qu’on soit dans une approche lean ou produit en général ! Ce qui apporte de la valeur, ce sont les fonctionnalités auxquelles ont accès les utilisateurs finaux. Tant qu’elles ne sont pas finalisées, les utilisateurs finaux n’y ont pas accès et ça n’apporte pas de valeur.
Illustration
Le travail en cours, le WIP peut se matérialiser de manière différente. Ça peut concerner :
L’avancement du développement de fonctionnalités au sein du produit. Un WIP important va donc se traduire par le fait qu’il y ait beaucoup de tickets qui ne sont pas finalisés. Souvent, comme évoqué à un autre endroit, c’est lié au fait que certains tickets vont avoir besoin d’une expertise ou de l’appui de quelqu’un dans l’organisation qui n’est pas disponible. C’est pour ça par exemple qu’on se retrouve parfois avec des sprints où on avait prévu de développer 10 fonctionnalités. Et où on se retrouve à finir 1 ou 2 fonctionnalités maximum tout en ayant démarré 5 ou 6 tickets sans les achever. Le problème est qu’on ne délivre de la valeur que pour ces quelques 1 ou 2 fonctionnalités mais pas pour ces 5 ou 6 tickets. Il aurait peut-être été plus judicieux de se focaliser sur un peu moins de tickets pour réussir à les finaliser également.
Le multi-tasking et l’absence de focus est aussi un signe qui montre que le WIP est trop important. Souvent, la raison sous-jacente est une insuffisante priorisation et des objectifs peu clairs. Du coup, faute de savoir vers où il faut aller, on va se disperser sur plusieurs sujets en parallèle. On va donc augmenter le WIP. Le risque pour autant, c’est que fatalement, on risque de ne pas assez mettre l’accent sur les sujets qui requièrent plus d’investissement, par exemple parce qu’ils apportent plus de valeur à nos utilisateurs finaux.
Mettre en pratique
L’objectif est de réussir à réduire le travail en cours (WIP) pour augmenter le productivité. Mais aussi parce que comme on l’a vu plus haut, cela traduit des problèmes sous-jacents significatifs. Quelques idées pour mieux contrôler et optimiser celui-ci :
→ Le management visuel et les tableaux Kanban. Ces outils sont très utiles pour visualiser le travail en cours. Comme on l’a dit plus haut, dans la tech, le WIP est invisible et immatériel à la différence de l’industrie. C’est donc une super manière pour faciliter la prise de conscience que trop de choses sont en cours et parasitent nos process et alourdissent notre charge mentale. C’est également une très bonne approche pour mettre en avant une limite au nombre d’items qu’on peut traiter en parallèle (avec par exemple une WIP limit de 3 items dans le schéma ci-dessous).
→ Les revues régulières du WIP. Une fois qu’on a objectivé et qu’on a mis en avant le WIP, il faut en profiter pour le surveiller de manière continue afin d’ajuster lorsque c’est nécessaire. Une manière simple de procéder peut être d’inclure un moment lors de chaque rétrospective. C’est à dire, à la fin d’un sprint, lorsqu’on fait un bilan des aspects positifs et négatifs, faire un mini focus sur le WIP et sa gestion au cours du sprint. Différentes actions peuvent être mises en place par la suite. Soit définir un plan d’actions ponctuel pour “désengorger” le WIP parce qu’il y a trop de choses prévues en parallèle dans une colonne. Soit ajuster à la hausse ou à la baisse la limite de WIP afin que celle-ci colle plus à nos besoins.
→ Le travail d’équipe en mode “task force”. Lorsqu’un WIP important apparaît au sein de l’équipe, il peut être pertinent d’essayer de regrouper plusieurs personnes pour avancer sur le même sujet. Typiquement si un développeur peine à finaliser une user story US1, cela vaut peut-être la peine de demander à un autre développeur de venir l’aider pour que celle-ci soit finie plus vite. Cet autre développeur pourrait démarrer une autre user story US2 mais se focaliser sur US1 permet de réduire le WIP. Surtout, si US1 est plus prioritaire qu’US2, il est préférable de la terminer d’abord, avant de lancer US2. Cette pratique a même un nom dans la tech, le “swarming” (pour les plus curieux).
Concept 6️⃣ - flow under uncertainty
Présentation du principe
Description
Reinertsen oppose ici deux notions :
→ Le flux de valeur qu’on est censé délivrer aux utilisateurs itération après itération. Cette valeur réside dans la solution qu’on apporte aux problèmes de l’utilisateur ou à ce qu’on lui permet d’accomplir.
→ L’incertitude inhérente au développement logiciel. On peut localiser cette incertitude à deux endroits principaux ici. D’une part au niveau du système informatique, de l’ordinateur ou du logiciel. Une matière incertaine et peu prédictible. D’autre part au niveau de l’utilisateur, de l’humain derrière l’écran. Cet utilisateur peut être imprévisible et adopter un comportement incertain, difficile à anticiper.
Reinertsen met en avant deux notions pour améliorer cette livraison du flux dans ce contexte d’incertitude :
→ La cadence : cela renvoie à créer des habitudes, du rythme dans les activités qu’on fait. Une réunion hebdomadaire permet d’avoir ce genre de rythme.
→ La synchronisation : il s’agit ici de s’assurer que les sous-parties d’une partie avancent de concert et en étant alignés sur les objectifs, contraintes et échéances.
Par exemple imaginons qu’on a 2 équipes produit qui développent des produits avec des interdépendances. La cadence passera par le fait que chacune de ces équipes possède différentes réunions habituelles qui mettent du rythme dans son travail. La synchronisation renvoie au fait que ces équipes ont également un rendez-vous régulièrement pour partager ensemble leur avancement.
Illustration
Zoomons sur ces deux notions et voyons ensemble comment elles permettent d’améliorer la gestion du flux, et plus largement, de maximiser la valeur apportée par celui-ci.
→ La cadence et le fait de faire des choses avec du rythme trouvent leur justification dans le comportement de “l’humain qui travaille”. La loi de Parkinson à cet égard, est intéressante. Elle nous dit que lorsqu’on a 1h pour effectuer une tâche, on va utiliser la totalité de l’heure. Et que si on réduisait cette durée à 30 minutes, on arriverait à la faire en 30 minutes. Même chose si on avait 2h, on utiliserait l’ensemble des 2h. Bref, plus on nous donne de temps, plus on va mettre de temps pour accomplir une tâche.
La cadence nous permet de lutter contre ça. Ou plutôt, elle va contenir ces durées et les empêcher d’être trop longues. En effet si on tire la ficelle jusqu’au bout, ça veut dire que si on a 6 mois pour faire quelque chose, on attendra la fin des 6 mois pour le faire ! C’est un peu extrême mais l’idée reste valable que lorsqu’on est moins sous pression en termes d’échéance, on est moins efficace. Avec des sprints de 2 semaines comme en agile, on a une échéance qui met du rythme et casse cette loi de Parkinson. Ensuite, comme on est plus efficace et productif, on délivre plus de fonctionnalités et donc on apporte plus de valeur.
→ Les synchronisations permettent de régler l’enjeu évoqué ci-dessus des dépendances entre équipes de développement. C’est un problème que l’on rencontre très rapidement. En fait dès qu’on construit un système qui devient volumineux, qui demande des nouvelles fonctionnalités régulièrement et implique de faire travailler plus d’une dizaine de développeurs en même temps. On va logiquement regrouper ces développeurs dans des équipes différentes. Le risque dans ces cas là, c’est que les équipes ne soient pas alignées et n’avancent pas dans la même direction. Si l’équipe B a besoin d’une fonctionnalité développée par l’équipe A. Il faut qu’elle puisse adapter son planning en fonction de l’avancement de l’équipe A. Inversement, c’est important que l’équipe A puisse en tenir compte dans sa priorisation.
Mettre en pratique
→ Synchronisation - organiser des réunions de synchronisation. Dès lors qu’on doit faire interagir un nombre important de personnes et d’acteurs, il est nécessaire de planifier des réunions régulières de synchronisation. Attention je ne parle pas ici de comités interminables avec 50 personnes connectées sur un teams et 47 en train de faire semblant d’écouter. Je parle de points dynamiques et efficaces pour s’assurer que tout le monde est aligné et va dans la même direction.
→ Synchronisation - utiliser des outils pour mettre en visibilité les dépendances. Au-delà des réunions qui se tiennent ponctuellement, on gagne beaucoup à disposer d’un endroit, d’un outil et d’un visuel qui synthétise de manière macro les dépendances et interactions entre acteurs.
En SAFe, on utilise un tableau de synthèse des dépendances comme celui ci-dessus. Je ne suis pas forcément fan de l’appliquer en toutes situations. En revanche, je le trouve très puissant en termes visuel pour matérialiser les interactions et besoins de synchronisation. C’est une très bonne source d’inspiration.
→ Cadence : mettre en place des cycles avec différentes tailles. Les cycles dont on parle vont correspondre aux itérations au cours desquelles on fait évoluer le produit. Plus les cycles sont longs, plus les évolutions sont significatives. Ces cycles sont emboîtés les uns dans les autres, avec une forme “d’oignon” comme on le voit sur le schéma ci-dessous. Ces cycles permettent de mettre du rythme et de la cadence. C’est à ça que servent notamment les sprints. Ils nous aident à combattre la tendance à tomber dans la “loi de Parkinson”. En effet, si j’engage 10 user stories dans un sprint qui dure 2 semaines, je sais que j’ai une échéance fixe. Il faut que je les aie réalisées pour la fin de ces 2 semaines. Je ne vais pas procrastiner et laisser filer ; de même, je serai d’autant plus motivé et j’aurai d’autant plus envie de finir à temps.
⚠️ Petite remarque : on n’a pas forcément besoin d’avoir autant de niveaux imbriqués ! Il faut être pragmatique et y aller progressivement. En tout cas, gardez bien en tête d’avoir a minima un niveau “court terme” (typiquement des sprints toutes les 2 semaines) et un niveau “moyen terme” (typiquement tous les 3-6 mois).
Concept 7️⃣ - fast feedback
Présentation du principe
Description
Reinertsen met ensuite en avant l’importance d’avoir du feedback rapide lorsqu’on développe un logiciel. Ces feedbacks rapides vont avoir des retombées positives à plusieurs niveaux que ça soit pour améliorer la qualité, réduire les risques ou permettre de tester plus rapidement des innovations.
Un des enjeux est de réussir à obtenir des retours fiables et rapides des utilisateurs sur une fonctionnalité qu’on a développé pour eux. Pour autant, cela peut aussi renvoyer à un feedback “technique”, pas explicité en tant que tel. Par exemple lorsque je déploie en production une version de mon produit, je vais récupérer des informations sur le déploiement et le fait qu’il se soit bien passé. Cela constitue un feedback plutôt “technique” mais tout aussi important.
Si vous me connaissez, vous vous doutez que je pense qu’il n’y a quasiment que des bénéfices à tout ça ! Et c’est également ce que nous dit Reinertsen. Par exemple, un feedback plus rapide permet :
→ 1️⃣ Une identification rapide des problèmes : Des retours rapides permettent aux équipes d'identifier et de résoudre les problèmes tôt, évitant que de petits problèmes ne deviennent plus importants et coûteux.
→ 2️⃣ Un apprentissage plus rapide : Les équipes peuvent apprendre des retours et adapter rapidement leur approche, assurant une amélioration continue.
→ 3️⃣ Une meilleure Gestion des Risques : Les retours rapides aident à détecter tôt les risques et permettent de mettre en place des stratégies d'atténuation en temps utile.
Illustration
Plusieurs méthodes et approches dans la Tech sont mises en place pour accélérer le feedback :
Un framework comme Scrum inclut notamment des démonstrations, en fin de sprint, afin de montrer aux sponsors et utilisateurs ce qui a été réalisé au cours du sprint. Idéalement, on peut aussi prévoir des démonstrations intermédiaires, c’est à dire qui anticipent cette démonstration finale. L’intérêt est de récupérer vite un feedback de la part des utilisateurs et sponsors. Tant qu’on ne leur montre que des slides ou qu’on ne partage que sur des principes théoriques, on a le risque que leurs retours soient biaisés. En confrontant les évolutions du logiciel directement avec eux, on augmente la probabilité d’avoir un vrai feedback qui nous permette de valider ou d’ajuster pour apporter encore plus de valeur.
Les approches DevOps également visent à accélérer le feedback au niveau technique. Le DevOps permet d’une part de tester plus rapidement par l’intermédiaire de tests automatiques. Ces tests constituent une 1ère forme de feedback. Si les tests fonctionnels ne sont pas validés, cela veut dire qu’il faut ajuster. Plus on a cette information vite, mieux c’est. D’autre part, le DevOps nous pousse à déployer le plus souvent possible (selon les approches small batch sizes vues plus haut). En déployant plus souvent, on accélère également la récupération du feedback (des utilisateurs ou juste du feedback technique).
Mettre en pratique
Dans la lignée des approches Scrum et DevOps, voici quelques idées d’actions pour obtenir une réelle accélération du feedback :
→ Favoriser une communication ouverte. De manière générale, plus les personnes se sentes libérées pour parler, plus cela accélère en retour le feedback. D’un côté, on est encouragé à montrer les choses. Il y a moins de pudeur et on ose plus demander des retours même si tout n’est pas encore parfaitement finalisé. De l’autre, cela encourage les autres à donner du feedback. De manière bienveillante évidemment. Mais on enclenche une dynamique vertueuse : + je suis prêt à recevoir du feedback, + je montre ce que je fais, + j’en reçois et je m’améliore, + ça m’encourage à en recevoir etc..
→ Intégrer des dispositifs de supervision / monitoring au niveau technique. Lorsqu’on développe un système informatique, on peut installer des “sondes techniques” qui vont permettre de surveiller (monitor en anglais) comment le système se comporte en pratique. Ce genre de dispositif est très intéressant car il permet également de récupérer du feedback. Du feedback technique ! Lorsqu’on déploie une nouvelle fonctionnalité, ces sondes nous permettent de “traduire” le feedback de l’application. Cela nous permet de savoir par exemple, si on a introduit des anomalies dans le système. Or, plus on a vite ces informations, plus on va pouvoir les corriger vite.
→ Mettre en place des rituels avec les clients : parce que leur feedback est le plus important, on peut s’inspirer des démonstrations scrum mais on peut également être inventif et penser à d’autres types de rencontres. Comme par exemple des points “communauté” où on va avoir des échanges très libres. D’ailleurs je vous conseille de ne pas uniquement utiliser les interactions client pour démo MAIS aussi pour les parties prototypes afin de sécuriser.
Concept 8️⃣ - decentralized control
Présentation du principe
L’idée de Reinertsen est ici de décentraliser le contrôle au maximum pour améliorer la prise de décision afin d’accélérer les temps de réponse.
Lorsque plusieurs intermédiaires interviennent dans un processus de prise de décision, cela ralentit le temps pour aboutir à une décision finale. En effet, il faut :
Prendre le temps d’informer tout le monde ;
S’assurer que chacun a bien compris les enjeux
Puis enfin, tout le monde doit être d’accord ou il faut a minima atteindre un consensus
Plus on rajoute d’intermédiaires, plus ce processus est complexe, plus cela met du temps.
La décentralisation va permettre d’améliorer et d’accélérer le processus de décision de deux manières :
→ D’abord via une plus grande marge de manoeuvre pour les opérationnels. Ce sont eux, qui sont au plus près des problématiques. Ils vont donc voir en premier les décisions à prendre. Puisqu’ils ont les mains dans le cambouis ils vont comprendre plus facilement les enjeux des situations et agir en conséquence. Plutôt que de faire remonter l’information aux chefs ou aux sponsors (dans ce cas on centraliserait le contrôle), ils peuvent prendre des décisiosn pertinentes à leur niveau (local ou décentralisé).
→ Ensuite en laissant les opérationnels, qui sont dans le feu de l’action, décider, on va aussi prendre potentiellement des décisions plus pertinentes. D’une part, parce que le fait de prendre des décisions plus rapides permet de ne pas rater les opportunités de décisions qui “se périment” (comme on l’a vu au-dessus). D’autre part, parce que les opérationnels sont les plus compétents pour gérer les sujets qui les concernent au quotidien. Quand un bug arrive dans une application, c’est bien plus efficace que ça soit un développeur qui bosse dessus chaque jour qui le résolve. Même chose ici.
Évidemment, il ne s’agit pas ici de tout décentraliser car certaines décisions très structurantes doivent rester au niveau central. En revanche, de nombreuses micro-décisions ont intérêt à être prises au niveau local comme on l’a expliqué.
Voici la grille de lecture proposée par SAFe à ce sujet :
Doivent être prises au niveau central (“Take”) les décisions qui sont :
Peu fréquentes
Avec des conséquences durables
Qui génèrent des économies d’échelle importantes
En revanche, on peut décentraliser (“Delegate”) les décisions qui, à l’inverse, sont :
Fréquentes
Susceptibles de se périmer rapidement
Requièrent une connaissance présente au niveau local
Mettre en pratique
Afin de progresser dans la bonne direction avec davantage de décentralisation, voici quelques idées. Elles vont surtout dans le sens de moins centraliser. Comme mentionné juste au-dessus, il faut garder certaines décisions au niveau central. Toutefois, j’observe qu’il est en général plus difficile d’aller dans le sens de la décentralisation que l’inverse. D’où mon focus d’abord sur :
→ Définir le périmètre d’autonomie des équipes. C’est important de se mettre d’accord, de manière formelle ou informelle, sur la marge de manoeuvre et les responsabilités des équipes. Il peut s’agir par exemple de permettre à l’équipe produit de faire évoluer les priorités au sein d’un sprint tant que l’impact reste limité. Dire clairement et explicitement que les équipes sont autonomes est un premier pas important pour leur permettre d’avancer dans cette voie. Bien sûr, ce n’est pas parce qu’un périmètre est défini qu’on ne peut pas le faire évoluer ensuite.
→ Établir des lignes directrices claires pour la prise de décision. Une liste de sujets sur lesquels le niveau local est autonome n’est pas suffisant. Il faut également donner des critères clairs sur la manières d’exercer cette liberté / autonomie. Des matrices de type RACI peuvent être utiles dans ce genre de situation. Cela permet de préciser les acteurs à informer ou consulter dans le cadre de ces décisions. L’idée n’est pas d’alourdir les choses, bien au contraire. Plutôt de limiter au max la charge mentale des équipes. Et aussi de les couvrir dans le cas où les conséquences d’une décision prise en autonomie seraient négatives.
→ Favoriser une culture de confiance et de responsabilité. C’est un dernier aspect qu’on sous-estime mais qui est particulièrement important. Parfois cela ne suffit pas de définir un périmètre d’autonomie accompagné de lignes directrices. La culture globale de l’entreprise doit permettre de prendre de telles décisions dans un climat sain et rassurant pour les équipes. Cela peut être plus compliqué qu’il n’y paraît car certaines organisations ont une rigidité forte au niveau de leur process et une culture de la remontée d’informations auprès de la hiérarchie. Pour enclencher une dynamique positive à ce niveau, le plus pertinent reste de mettre en place des actions petit à petit (des actes > des discours). Les deux premiers bullet points constituent donc une bonne solution pour faire évoluer ces sujets.
Conclusion
Merci de m’avoir suivi dans cette édition. C’était un peu long mais j’espère que ça a été intéressant pour toi et que ça t’a appris des choses.
On se retrouve dimanche prochain 🙏
Bon courage pour la semaine 😃
Victor