La mémoire subversive de nos systèmes legacy

Points clés

  • La dette technique est souvent le symptôme visible d'un phénomène plus profond : la perte de mémoire d'un système
  • Un système peut être complexe et rester maîtrisable, la difficulté apparaît quand on ne peut plus expliquer son état
  • Cette perte de mémoire a des causes identifiables, parmi lesquelles le turnover, le couplage fort ou les correctifs successifs
  • Reconstituer la mémoire d'un système, c'est débloquer du potentiel gelé : des choix qu'on croyait figés et qui ne le sont plus, des évolutions qu'on avait cessé d'envisager
  • Reconstruire la compréhension est une condition préalable à toute modernisation, l'IA rend cet effort enfin envisageable

Bibliothèque ancienne avec des étagères en bois chargées de livres et des bustes d'hommes

Il y a des situations que beaucoup d'équipes connaissent : on a identifié la cause d'un problème, on sait où elle se trouve dans le code et pourtant, on décide de contourner plutôt que de corriger. Pas par manque de compétence, mais parce qu'on n'est plus tout à fait sûr de ce qu'on va déclencher en touchant à cet endroit.

C'est rarement le signe d'un problème de code. C'est souvent le signe que quelque chose de plus fondamental s'est dégradé dans le système.

Ce phénomène ne se voit pas au début. Il s'installe progressivement, presque silencieusement, au fil des changements. On parle souvent de complexité, de dette technique ou de manque de tests. Ces diagnostics sont utiles, mais partiels : ils décrivent les symptômes visibles sans toujours capturer le mécanisme sous-jacent. Ce mécanisme est moins une accumulation de code qu'une érosion progressive de la mémoire du système. Par système, on entend ici quelque chose de plus large que le code : les décisions qui l'ont façonné, le contexte dans lequel elles ont été prises, et les personnes qui les portaient. C'est cette totalité qui s'érode, pas seulement les lignes de code. Ce qu'on perçoit comme complexe est souvent autant le reflet d'une méconnaissance que de sa réalité.

Dans de nombreuses applications, il existe une partie du système que tout le monde connaît, sans toujours la maîtriser complètement. Construite au fil du temps par des équipes successives, dans des contextes différents, elle embarque progressivement des contraintes qui n'existent plus nécessairement aujourd'hui. Les responsabilités se superposent, les dépendances s'entrelacent, les frontières deviennent floues. Ce qui était local devient structurel.

Chaque modification, même ciblée, peut produire des effets difficiles à anticiper, non pas à cause de la complexité en soi, mais parce que le couplage entre les éléments du système fait qu'un changement à un endroit peut en affecter d'autres, parfois très éloignés. Le système reste opérationnel. Mais on ne sait plus vraiment comment il fonctionne, ni comment nos modifications vont impacter le système.

Quand on n'ose plus toucher au code

À mesure que cette dynamique s'installe, un basculement apparaît.

Dans un système qu'on maîtrise, un changement est une décision. On anticipe, on raisonne, on ajuste. Dans un système qu'on ne comprend plus vraiment, un changement devient une hypothèse. On modifie, on observe, on corrige après coup.

C'est à ce moment que certaines zones du système commencent à être évitées. Non pas parce qu'elles sont techniquement inaccessibles, mais parce que leur comportement global n'est plus suffisamment prédictible. Une règle implicite s'installe : "on évite d'y toucher".

Sur un projet hôtelier, une brique gérait la disposition des clients dans les chambres : combinaisons possibles selon les règles métier, contraintes de capacité, cas particuliers. Une logique dense, centrale dans le process, construite et affinée sur des années. Le code fonctionnait, mais sans tests et sans historique, personne ne savait plus vraiment pourquoi certaines règles étaient là. Le faire évoluer, c'était avancer sans filet.

Ce que l'on appelle souvent dette technique est en réalité l'effet visible d'un phénomène plus profond : la perte progressive de mémoire du système. Avec le temps, ce qui disparaît n'est pas seulement la documentation ou les tests. C'est la capacité à répondre à des questions simples mais essentielles : pourquoi cette règle existe-t-elle ? Dans quel contexte a-t-elle été introduite ? Est-elle encore pertinente aujourd'hui ?

C'est aussi la difficulté à comprendre la structure réelle du système : ses dépendances critiques, ses zones modifiables, ses points de fragilité. Et c'est enfin l'écart croissant entre ce que l'on pense que le système fait… et ce qu'il fait réellement en production.

Un système peut être complexe et rester maîtrisable tant que sa logique reste compréhensible. La difficulté apparaît lorsque deux dynamiques se désalignent : la capacité à faire évoluer le système, et la capacité à expliquer son état. Le code évolue, les comportements changent, mais le sens des décisions passées s'efface.

Ce phénomène résulte souvent de trois facteurs combinés.

Le turnover des équipes d'abord : les personnes qui partent emportent avec elles le contexte dans lequel les choix ont été faits, pas seulement la connaissance du code. C'est la chaîne de sens des décisions qui se perd.

Le couplage fort entre les briques ensuite : quand les éléments sont fortement liés, on ne sait plus distinguer ce qui relève d'une vraie contrainte de ce qui est simplement l'héritage d'une décision passée, prise dans un contexte qui n'existe plus.

Les correctifs successifs enfin : ajoutés dans l'urgence et rarement capitalisés, ils effacent progressivement la frontière entre ce qui a été voulu et ce qui a été subi.

La pression des délais vient souvent amplifier ces trois dynamiques : en privilégiant la livraison sur la qualité, elle réduit l'espace pour capitaliser et accélère l'érosion.

Ce que le refactoring ne répare pas

Face à ce constat, la réaction naturelle est de chercher des solutions. Et les bonnes pratiques ne manquent pas : tests de caractérisation, refactoring progressif, documentation, ADR, simplification architecturale. Ces approches sont nécessaires. Elles permettent de stabiliser des zones du système et de réduire certains risques.

Mais elles agissent principalement sur la structure actuelle. Elles améliorent ce qui est visible, sans toujours restaurer le lien entre cette structure et les décisions qui l'ont produite. Une équipe peut très bien refactoriser un module, le rendre lisible, le couvrir de tests, et rester incapable d'expliquer pourquoi il est structuré ainsi, ni si cette structure a encore un sens aujourd'hui.

Ce ne sont pas les outils qui sont insuffisants. C'est l'objectif qu'on leur assigne. Employés pour améliorer la structure, ils rendent le système plus propre. Employés pour reconstituer la mémoire, ils permettent de comprendre pourquoi le système a été structuré ainsi, et si cela se justifie encore. Or c'est précisément ce lien qui constitue la mémoire du système. Sans cela, même un système propre reste difficile à faire évoluer car sa logique reste opaque. Le problème n'est pas résolu, il est simplement rendu plus présentable.

Reconstituer la mémoire

Si la perte de mémoire est au cœur de la difficulté à faire évoluer le système, alors la modernisation ne peut pas se limiter à le transformer. Elle doit aussi restaurer progressivement la compréhension qu'on en a.

Cette reconstruction s'appuie sur des pratiques que beaucoup d'équipes ont déjà en place mais rarement exploitées sous cet angle.

Les tests de caractérisation d'abord. On les utilise généralement pour sécuriser des changements. Mais quand un comportement inattendu apparaît, au lieu de simplement le figer, on peut l'annoter : "ce comportement est-il voulu ou subi ?" et en faire un point d'investigation. Les tests ne racontent plus seulement ce que le système fait. Ils commencent à dire ce qu'on ne comprend plus.

Les ADR, tickets ou historiques d'équipe ensuite. On les produit souvent comme documentation après coup. Exploités autrement, ils deviennent un point de départ pour interroger le système tel qu’il est : "cette décision tient-elle encore aujourd'hui, et dans quel contexte a-t-elle été prise ?" Ce changement de posture permet de reconnecter l'état actuel aux arbitrages qui l'ont produit et de redonner du sens à des décisions qui semblaient devenues arbitraires.

L'observabilité enfin. Les logs, traces et métriques servent généralement à surveiller et alerter, et à stabiliser la production quand quelque chose déraille. Mais une fois l'incident résolu, on peut aller plus loin : "ce comportement existe depuis quand, et qu'est-ce qu'il révèle sur l'usage réel du système ?" Les métriques ne racontent plus seulement ce qui s'est passé. Elles commencent à dire ce que le système est vraiment devenu. Une mémoire vivante, souvent présente mais rarement exploitée comme telle.

Ces différents axes ont toujours été à notre disposition. Ce qui a longtemps freiné leur adoption, c'est le coût d'entrée : naviguer dans des zones de code peu connues, corréler des comportements à des structures, formuler des hypothèses sur des intentions implicites demandait du temps que les équipes n'avaient pas.

L'IA modifie cette dynamique. Rétro-documentation, explication de code legacy, reconstitution d'intentions implicites. Ce qui demandait des jours peut aujourd'hui s'amorcer en très peu de temps. Elle ne résout pas tout : elle peut se tromper sur l'intention d'un code, et ses réponses restent à valider. Mais utilisée avec discernement, elle réduit suffisamment la friction pour que cet effort devienne enfin envisageable.

Mais reconstituer la mémoire ne fait pas que faciliter la modernisation. Cela change aussi la façon dont on regarde le système.

La mémoire est subversive

Reconstituer la mémoire d'un système n'est pas neutre.

Ce processus ne se limite pas à expliquer le passé. Il modifie la lecture du présent. Comprendre pourquoi un système est structuré d'une certaine manière conduit souvent à constater que certaines contraintes n'ont plus de justification, que certaines complexités ne sont plus nécessaires, et que certaines dépendances peuvent être remises en question.

La mémoire ne se contente donc pas d'expliquer : elle recontextualise. Elle rend à nouveau visibles des décisions devenues implicites. Et par là, elle rouvre des espaces de choix que l'on croyait fermés.

C'est pourquoi la modernisation des systèmes legacy est rarement un problème purement technique. Ce qui se dégrade en premier, ce n'est pas le code. C'est la capacité collective à comprendre ce que le système fait, pourquoi il le fait, et ce qu'il serait raisonnable d'y changer.

Un système que l'on ne comprend plus ne se transforme plus vraiment. Il se contourne, il se stabilise, il se subit.

Reconstituer cette mémoire devient alors un enjeu central : non pas pour documenter le passé, mais pour redonner aux équipes la capacité d'agir avec lucidité sur le présent. Elle n'explique pas tout. La perte de mémoire est souvent le reflet de dynamiques plus larges, organisationnelles et culturelles, qui conditionnent la façon dont les équipes construisent, transmettent et font évoluer leurs systèmes. Mais c'est un autre sujet.

L'enjeu n'est plus de moderniser en espérant comprendre, mais de reconstruire la compréhension comme condition préalable à toute modernisation.

Références :