La fin de la "dette technique" : du passé ne pas faire table rase

Dans les articles qui précèdent, j'ai exprimé l'idée de remplacer, dans le modèle que nous utilisons lorsque nous parlons de "gérer la dette technique" d'une solution logicielle, le diagnostic :

Notre solution est endettée techniquement

par l'hypothèse :

Notre solution repose sur des procédés en conflit

Cette hypothèse permet de répondre plus efficacement au problème de la "dette technique" en ce qu'elle substitue à une métaphore inopérante des outils permettant d'appréhender plus précisément et plus efficacement le problème en question.

Le propos n'est pas de nier l'existence de la "dette technique" en tant que symptôme. Quelques mois d'expérience dans le domaine du développement de logiciel suffisent en général pour se faire une idée du phénomène observé. Par exemple :

  • le code d'une solution est moins facile à comprendre et à modifier lorsqu'il semble n'obéir à aucun principe de nommage, de découplage et de cohésion ;
  • l'avantage de productivité obtenu en livrant du code sans aucun test unitaire est seulement de courte durée ;
  • un changement brusque d'objectif, de contrainte, ou d'architecture laisse souvent des traces indélébiles dans la conception d'une solution ;
  • faire évoluer du code écrit il y a longtemps par d'autres développeurs est non seulement difficile mais également risqué ;
  • etc.

Tous ces constats sont réels. Souvent, la réponse des entreprises consiste à rassembler ces constats sous le terme générique "dette technique", pour ensuite installer des outils permettant de "suivre l'endettement", afin d'en calculer finement le "coût" en euros sur une feuille de calcul. Or cette stratégie ne permet pas de résorber le phénomène observé. Elle s'appuie sur une idée vague, et il est très rare qu'une idée vague nous rapproche d'une solution concrète.

Que faire donc ?

Il faut d'abord considérer le contexte dans lequel la "dette technique" constitue un problème pour nous. On peut se trouver devant trois situations-types :

  1. prêts à commencer le développement d'une nouvelle solution,
  2. sur le point de nous voir confier la maintenance d'une solution existante,
  3. en charge de la maintenance évolutive d'une solution existante.

NB : si vous êtes concerné mais pas opérationnellement impliqué dans le travail de maintenance ou de développement en question, vous n'avez aucun problème qu'il faille qualifier de "dette technique" (mais vous pouvez avoir un problème d'objectifs, de contraintes, de moyens, de ressources, de délégation, etc.).

Prévenir la "Dette Technique" sur un développement nouveau

C'est la situation la plus simple. Intégrez au processus de cadrage global du projet une étape de cadrage de l'état de l'art du projet. L'objectif de cette étape est triple :

  • vérifier et valider explicitement l'adaptation de l'état de l'art aux objectifs et aux contraintes du projet,
  • vérifier que l'équipe en charge de la réalisation de la solution maîtrise cet état de l'art,
  • identifier les procédés dans cet état de l'art qui présentent d'entrée de jeu une possibilité de conflit.

Une façon particulièrement efficace d'effectuer ce cadrage consiste à réunir l'équipe et recenser avec elle tous les procédés que chacun entend mettre en œuvre sur le projet. On classe ensuite (approximativement) les procédés sur un axe horizontal exprimant le degré d'accord de l’équipe concernant ce procédé, sur un axe vertical son aspect tacite ou explicite. Pour ce faire, la personne qui facilite l'exercice pose deux questions à propos de chaque procédé :

  • Est-ce que vous êtes tous d'accord pour appliquer le procédé tel qu'expliqué ?
  • Avez-vous déjà discuté de ce procédé auparavant ou est-ce la première occasion de le faire ?

À la fin de l'atelier, le quadrant récapitule tous les procédés significatifs constituant l'état de l'art de l'équipe pour ce projet.

La zone située en haut à droite du quadrant contient les procédés qui font explicitement l'objet d'un accord, d'un contrat, ou qui ont été abordés, discutés et résolus (possiblement durant l'atelier)

La zone située en bas à droite du quadrant contient les procédés formant la base de la culture technique de votre équipe : l'ensemble des pratiques et règles qui sont communément admises et sur lesquelles il n'y a nul besoin de revenir.

La zone située en haut à gauche du quadrant contient les procédés en conflit qui posent un problème, c’est à dire dont la résolution permettrait à l’équipe de gagner en efficacité, en qualité, ou en cohésion. Dans cette zone 'on trouvera souvent les grands conflits habituels (et sempiternels) tels que “prendre le temps de faire du code propre” vs “modifier le code au plus vite” (pour prendre un seul exemple).

La zone située en bas à gauche du quadrant contient les procédés qui étaient jusqu'à maintenant implicites et qui menacent de dégrader la cohérence de la solution ou l’efficacité de l’équipe au cours du projet. Par exemple, l'équipe note que les outils de suivi de l’activité et de gestion de version, qui permettent d’identifier immédiatement le responsable d’une erreur de conception ou de programmation, entrent en contradiction avec le principe du droit à l'erreur, qui est nécessaire à toute recherche de solution, et que c'est en vertu de cette absence de droit à l'erreur que les séances d’estimation en début d’itération sont si souvent (trop) longues et (bien trop) méticuleuses.

Les discussions qui jalonnent cet atelier permettent donc à l'équipe de clarifier ses procédés, de les rassembler en un état de l'art, et de mieux prévenir les dégradations possibles de cet état de l'art. Elles conduisent à une équipe plus cohérente.

Reprise d'une solution existante "legacy"

Dans une situation de reprise d'une application "endettée", les conflits de procédés qui ont marqué techniquement l'évolution de cette solution appartiennent au passé. Que pouvons-nous faire ?

Nous pouvons étudier autant que possible l'histoire du projet, afin d'identifier quels procédés constituaient l'état de l'art initialement défini lors de la création de cette solution, et retracer la manière dont ces procédés ont évolué et se sont, dans certains cas, contredits.

Nous pouvons faire une ré-évaluation du projet courant concernant cette solution, en ne nous limitant plus seulement aux artefacts techniques figés qui la caractérisent (code, documentation, qualimétrie) mais en considérant également l'histoire de l'état de l'art qui a entouré cet asset depuis sa création, et en (se) posant des questions :

  • Quelles décisions concernant l'état de l'art adopté pour la construction découlaient nécessairement des contraintes et objectifs initiaux du projet ?
  • Quelles décisions ont été prises indépendamment (ou en dépit) de ces contraintes et objectifs ?
  • Quelles nouvelles contraintes (limites nouvelles de temps, de connaissances, de budget, de disponibilité etc.) ont mené à des conflits de procédés dans l'état de l'art de l'équipe ?
  • Quels nouveaux objectifs (fonctionnalités, performances, niveau de service, etc.) ont mené à des conflits de procédés dans l'état de l'art de l'équipe ?
  • Quelles décisions alternatives concernant l'état de l'art, les ressources disponibles ou la communication, si elles avaient été accessibles à temps, auraient permis de résoudre (plus rapidement) ces conflits ?
  • Quels conflits similaires à ceux qui se sont produits dans le passé pourraient se produire à nouveau dans le contexte, les contraintes et les objectifs du nouveau projet de reprise ?

Enfin, nous pouvons effectuer un recadrage du projet dans lequel nous considérons ces trois états de l'art distincts :

  1. état de l'art du projet initial et tel qu'il a évolué jusqu'à aujourd'hui (issu de l'étude de l'existant),
  2. état de l'art minimal de référence pour l'organisation dans laquelle la reprise s'effectue,
  3. l'état de l'art de l'équipe chargée de cette reprise,

et procédons à la définition d'un état de l'art pour le projet de reprise qui puisse résoudre les conflits identifiés.

Travail en cours sur une solution existante "endettée"

Il s'agit de la situation dans laquelle une équipe (au sens large, c’est à dire incluant son client, son manager, son Product Owner) constate que la "dette technique" réduit fortement son efficacité et détériore son enthousiasme. Dans cette situation, la meilleure chose à faire est de mettre en pause le travail de maintenance, de procéder à un recadrage du projet (section précédente), puis de reprendre le travail de maintenance sur la base du nouvel état de l'art élaboré pendant le cadrage.

La décision de mettre en pause la maintenance et de procéder à un recadrage de l’état de l’art du projet peut paraître difficile à défendre : comment faire accepter de "stopper la machine en vol" ? C'est pourtant souvent la décision la plus rationnelle et la plus réaliste qu'il soit possible de prendre, au vu de l'état de l'application concernée :

  • Le système de développement tourne "au ralenti" : temps de recette allongé du fait des nombreuses régressions, nécessité de requérir à une étude d'impact avant chaque évolution (même mineure), temps de montée en compétence incompressible de plusieurs mois…
  • Les acteurs en présence dans ce système ne sont plus d'accord entre eux : le Product Owner préconise de créer plus de features plus vite, les développeurs préconisent de refondre l'ensemble de la solution, le management temporise en attendant un grand projet de rationalisation…
  • L'équipe est en désarroi : les plus exigeants démissionnent ou menacent de le faire, les moins expérimentés s’habituent et prennent pour valeur de référence un état de l'art compromis, le moral de l'équipe est en berne, chacun se réfugiant dans la défensivité, l'indifférence ou le cynisme.
  • Il n'y a aucun scénario possible dans lequel le coût financier et humain d'un tel projet pourrait diminuer si rien n'est fait : à objectifs constants, plus un asset se détériore, plus il coûte cher à maintenir.

Et si mon manager, mon client ou mon équipe "ne veulent pas entendre parler de conflit" ?

Si tel est le cas, il y a un risque que la culture de votre entreprise soit réfractaire aux conflits. C'est à dire qu'elle rencontre — comme toute entreprise qui cherche à innover, ou améliorer ses résultats dans son activité informatique — des conflits, mais qu'elle ne les considère comme tels et ne les traite réellement que lorsqu'il est très tard. Dans une telle culture, on ne gère pas les conflits, on ne gère que des crises, parce qu'un conflit non géré se transforme inévitablement en crise. Quelques exemples :

Incohérence : Les développeurs, qui n'étaient pas d'accord sur le type de traitement à accorder aux cas d'erreurs, ont décidé de travailler chacun selon son idée. L'application traite différemment les cas d'erreurs selon la personne qui était en charge de telle ou telle partie du système. Un cas d'erreur a été incorrectement traité, et n'a pas a été détecté en phase de recette bien que la procédure de test inclut un parcours exhaustif des logs d'exécution, à la recherche d'erreurs (le traitement de cette erreur ne provoque pas d'écriture dans les logs).

Drame : Les développeurs n'arrivent pas à faire entendre leur demande de budget pour une opération visant à améliorer la structure et les tests automatisés de l’application. À la place, on leur demande de livrer rapidement des nouvelles features, ce qu'ils acceptent de faire. Lorsque la mise en production de l’application se solde par une série d'incidents préjudiciables au chiffre d'affaire et à l'image de l'entreprise, la direction demande des comptes. Les développeurs, dont la sécurité est en jeu, adoptent des comportements individuels rigides leur permettant de restaurer leur sécurité : pointer du doigt (les bugs, les collègues ou le management), se déclarer victimes (des circonstances, ou du management). Pour le manager, discuter avec eux (de n'importe quel sujet) devient difficile. Un conflit de territoire s'installe.

Retard : Lors du cadrage d'un projet, les discussions entre les développeurs et les architectes de l'entreprise mettent en lumière plusieurs conflits d'idées. Sous la pression de la direction métier, qui souhaiterait entendre que le projet a démarré, au lieu d'entendre qu'on discute encore et toujours de son architecture, le manager impose à l'équipe un tableau RACI dans lequel les différentes responsabilités sont attribuées de manière à éviter le recours aux discussions. Ce cloisonnement entraîne un mode de développement dans lequel les décisions sont déléguées, reportées, contredites (silencieusement), prises en "fait accompli", masquées, contournées. Chaque discussion nouvelle est examinée en regard du tableau RACI, et produit un nouvelle attribution, un nouveau raffinement du processus, et son ralentissement inéluctable. Un projet qui demanderait quelques semaines à une organisation agile nécessite plus d'un an et demi pour livrer une solution à peine acceptable.

Un conflit de procédés est un conflit d'idées. Ce conflit d'idée est nécessairement conditionné par une limite de ressources. Ces idées sont toujours portées (mises en avant, défendues, ou rejetées) par des personnes.

Lorsqu'un conflit d'idée est différé ou ignoré au lieu d'être résolu, ce conflit persiste, jusqu'à devenir critique en regard des ressources utilisées. Lorsqu'un conflit a été différé ou ignoré au point qu'il provoque une crise, alors le climat qui entoure ce conflit rend son traitement plus difficile pour les acteurs concernés : urgence, enjeux, l'erreur n'est plus possible. Dans un tel climat, le comportement humain le plus fréquent (dans la plupart des entreprises, en 2019, en tout cas) est d'entrer dans le triangle dramatique : blâme, victime, secourisme. Cette situation dramatique va marquer chacun au point d'influencer sa manière d'aborder le prochain conflit. (Observez autour de vous et en vous : la moquerie, la plainte, et une attitude de surprotection sont des signaux faibles de ces drames potentiels).

En résumé, un conflit d'idées différé ou non résolu a toutes les chances de provoquer une crise, qui entraînera un drame, lequel drame entraînera — dans le souvenir de toutes les personnes impliquées — une difficulté supplémentaire à envisager, naviguer et résoudre les prochains conflits d'idées. Une équipe (au sens large) qui ne traite pas les conflits d'idées à temps ne peut pas gagner en cohésion. Une équipe incohérente fabrique des logiciels incohérents.