🔗
Madic - Janvier 2025 - Juin 2025 - St André de Cubzac

Réinternalisation d’un ensemble de plus de 5 millions de lignes de code .NET, développé et maintenu pendant des années par une ESN. L’architecture présentait une complexité largement supérieure aux besoins identifiés et l’entreprise envisageait une réécriture complète en Python.

Audit du système et accompagnement de l’équipe interne. Démonstration que le problème n’était pas la technologie mais une complexité largement disproportionnée par rapport aux besoins : 45 % du code d’une partie témoin pouvait être supprimé à fonctionnalités équivalentes. Reprise progressive de la maîtrise technique, amélioration des performances et mise en place de pratiques de tests plus efficaces.

Réinternaliser un monstre

Madic venait de reprendre en interne une application développée par une ESN pendant plusieurs années. L’objectif était de permettre à l’équipe interne de retrouver progressivement la maîtrise technique du système et de pouvoir en assurer directement l’évolution.

Le système représentait un actif logiciel considérable : plus de 5 millions de lignes de code réparties sur plus de huit solutions .NET. Les versions utilisées étaient récentes et l’ensemble pouvait, au premier regard, donner l’impression d’un système moderne et maîtrisé.

L’entreprise envisageait pourtant de repartir de zéro, en Python. Lorsque je cherche à comprendre les motivations de ce choix, aucune contrainte technique précise ne justifie alors le changement de technologie. Le projet semble surtout motivé par la volonté de repartir sur une base perçue comme plus moderne.

Mon rôle initial est celui d’un expert .NET capable également d’intervenir en Python. Je considère cependant dès le départ qu’une réécriture serait prématurée : l’entreprise possède déjà un actif .NET important, le logiciel fonctionne et rien ne démontre que le langage constitue le problème.

Deux semaines pour comprendre le problème

Je réalise un audit de deux semaines portant sur le code, l’architecture, les bases de données, les performances SQL et Entity Framework, les tests, les dépendances, la chaîne de développement et les pratiques de l’équipe.

Le constat est plus sévère que prévu.

L’application présente un niveau d’abstraction particulièrement élevé. Les mêmes mécanismes sont répétés à grande échelle, parfois avec une abstraction ne possédant qu’un seul type concret. Plusieurs pans du code présentent ainsi une complexité qui ne semble pas justifiée par les besoins fonctionnels identifiés.

Le système possède par ailleurs plusieurs milliers de tests unitaires et affiche environ 95 % de couverture de code. Pourtant, aucun test d’acceptation ou end-to-end ne protège le comportement global de l’application.

Un passage en mutation testing permet de mesurer la différence entre quantité de tests et efficacité réelle : avec 95 % de couverture, seuls environ 20 % des mutants sont détectés.

La couverture est élevée, mais la capacité des tests à détecter une régression est faible.

Le problème n'est pas .NET

Je rédige un rapport d’audit d’environ 50 pages à destination du chef de projet et de sa hiérarchie. Les problèmes sont classés selon leur gravité et leur fréquence afin de distinguer les risques réels de la simple dette technique.

La conclusion est simple : il n’est pas nécessaire de réécrire le logiciel.

Le système fonctionne et sa dette provient principalement d’une complexité excessive. Une réécriture aurait supprimé une partie de cette complexité, mais au prix de la réimplémentation de millions de lignes et surtout de la reconstruction de la connaissance métier accumulée dans l’existant.

La recommandation est donc de conserver le système, de réduire progressivement sa complexité et de renforcer l’équipe interne afin qu’elle puisse en reprendre la maîtrise technique. Un accompagnement ponctuel peut compléter cette montée en compétence, mais la connaissance du legacy doit progressivement rester au sein de l’organisation.

Mesurer la complexité plutôt que la subir

Une partie représentative du projet est utilisée comme terrain d’expérimentation. En conservant les mêmes fonctionnalités, environ 45 % du code peut être supprimé.

Cette expérience permet de rendre concrète une dette qui était jusque-là difficile à appréhender : une part importante de la complexité du système n’apporte aucune valeur métier.

Le travail porte également sur les performances de la base de données et d’Entity Framework, qui sont améliorées au cours de la mission.

Une culture de la simplicité est progressivement introduite dans l’équipe : préférer le code simple à l’abstraction prématurée, remettre en question les couches inutiles et appliquer le principe KISS lorsque le métier ne justifie pas davantage de complexité.

Reprendre le contrôle du legacy

L’équipe interne est de taille réduite au regard de la complexité et de la taille du système. L’accompagnement doit donc permettre de renforcer progressivement son autonomie technique.

Je les accompagne pendant sept mois dans la reprise du projet, avec un objectif qui dépasse la simple résolution de problèmes techniques : transmettre les pratiques nécessaires pour travailler efficacement avec un legacy et tester les évolutions apportées au système.

Les tests des nouvelles fonctionnalités sont réécrits selon une approche beaucoup plus exigeante. Leur score de mutation dépasse alors 80 %. Le temps disponible ne permet cependant pas de reprendre l’ensemble de l’historique du projet.

Le responsable de l’équipe apporte de son côté une connaissance métier approfondie. Ce binôme entre connaissance fonctionnelle et expertise technique permet de distinguer les contraintes réellement nécessaires des complexités héritées du système.

L'équipe interne reprend le projet

À l’issue des sept mois d’accompagnement, l’équipe interne a repris progressivement la responsabilité du logiciel.

La poursuite de la simplification et de la modernisation s’effectue progressivement, au rythme des priorités du projet.

L’équipe dispose désormais des connaissances et des pratiques nécessaires pour comprendre, tester et faire évoluer directement son application.

Ce que cette reprise a réellement changé

Le projet n’avait finalement pas besoin d’un changement de langage. Il avait besoin de moins de complexité, de meilleurs tests et d’une équipe capable de comprendre ce qu’elle maintenait.

L’intervention a permis d’éviter une réécriture sans justification technique, de permettre à l’équipe interne de reprendre la maîtrise du logiciel et de poser les bases d’un pôle de développement interne.

Un legacy n’est pas forcément un vieux logiciel. Parfois, c’est un logiciel récent rendu inutilement compliqué par les années de développement.