Legacy — ce n’est pas simplement du vieux code. C’est un système fonctionnel qui rapporte de l’argent à l’entreprise mais freine le développement. Dans le développement mobile, le legacy peut être écrit en Objective-C, utiliser des bibliothèques obsolètes ou des motifs d’architecture dépassés. Selon un rapport de CAST Software (2024), l’âge moyen d’une ligne de code dans les projets enterprise dépasse 14 ans. La stratégie de travail avec le legacy détermine s’il deviendra un frein ou restera un actif gérable.
Points clés
Legacy — code ou système qui continue de fonctionner en production mais ne répond plus aux normes de qualité modernes. Le legacy peut être écrit dans un langage obsolète (par exemple, Objective-C au lieu de Swift), utiliser des bibliothèques non supportées ou des motifs d’architecture considérés comme des antipatterns.
La caractéristique principale du legacy est l’absence de tests. Selon la définition de Michael Feathers (2004), le code legacy est du code sans tests. Si on ne peut pas modifier le comportement en toute sécurité, le système est en statut legacy quel que soit son âge. Du code frais sans tests unitaires est legacy dès le premier jour.
Le legacy n’est pas nécessairement mauvais. Un système bien conçu en Java 8 peut être plus fiable et compréhensible qu’un code chaotique en Kotlin avec des coroutines. L’âge du code n’est pas un indicateur de qualité — ce qui compte, c’est la facilité avec laquelle le système peut être modifié et étendu.
Tout système réussi devient un legacy avec le temps. C’est un processus naturel : les technologies évoluent plus vite que le code ne peut être réécrit. Une application écrite il y a 5 ans en Swift 2 est legacy aujourd’hui, même si elle était moderne à sa création.
La valeur métier du legacy est souvent sous-estimée. Le système fonctionne de manière fiable, traite des transactions, stocke des données — la réécriture comporte des risques. Selon le Standish Group (2024), 35% des projets de réécriture complète se soldent par un échec. Économiquement, il n’est pas justifié de se débarrasser du legacy, mais d’apprendre à travailler avec.
Les meilleures stratégies sont la migration progressive, l’encapsulation de l’ancien code derrière de nouvelles interfaces et les tests automatisés. Le legacy ne devient un problème que lorsqu’il cesse d’être modifiable à un coût prévisible.
Absence de tests automatisés — l’indicateur principal. Si après avoir modifié une seule ligne un développeur ne peut pas exécuter de tests et confirmer que rien n’est cassé — vous avez affaire à du legacy. Un signe supplémentaire : le processus de déploiement prend des heures et nécessite des étapes manuelles.
La documentation ne correspond pas au code — un autre marqueur. Les diagrammes d’architecture sont obsolètes, les commentaires décrivent un comportement qui a déjà changé. Le temps d’adaptation pour un nouveau développeur dépasse un mois — signe d’une complexité élevée et d’une faible maintenabilité.
Signes supplémentaires : architecture monolithique sans limites claires, tests manuels comme méthode de vérification principale, pipeline CI long (plus de 30 minutes), utilisation de bibliothèques sans versions à jour et incapacité à mettre à jour les dépendances sans casser les modules connexes.
Le phénomène du code fragile — une modification à un endroit en casse trois autres. C’est une conséquence du couplage fort, lorsque les modules en savent trop les uns sur les autres. Plus le couplage est élevé, plus le système passe rapidement dans la catégorie legacy.
Ralentissement — le risque principal. Ajouter une fonctionnalité simple nécessite des heures d’étude du code et des jours de test. Selon Stripe (2024), les développeurs consacrent 33% de leur temps à surmonter la dette technique, directement liée à la présence de modules legacy dans le projet.
Fuite d’expertise — les auteurs du code original quittent l’entreprise et la documentation est incomplète. Les nouveaux développeurs craignent de toucher aux modules inconnus, ce qui conduit à l’effet de code gelé : le module n’évolue pas mais continue de fonctionner. Le bus factor de ces systèmes est critique.
Sécurité — les bibliothèques obsolètes contiennent des vulnérabilités connues. Utiliser OpenSSL 1.0.2 ou des versions anciennes de Jackson dans des projets Java est un chemin direct vers des incidents de sécurité qui peuvent coûter réputation et clients à l’entreprise.
Démotivation de l’équipe — travailler avec du legacy sans stratégie d’amélioration réduit la satisfaction des développeurs. L’équipe cesse d’être fière du produit, le turnover augmente, ce qui ralentit encore plus le développement du système.
Tests de caractérisation — la première étape avant toute modification de code legacy. Exécutez le code avec des données d’entrée connues et enregistrez la sortie attendue. Ces tests capturent le comportement actuel comme spécification. Golden master testing est une variante où la sortie est comparée à un fichier de référence.
Analyse des seams — trouver les points où le couplage peut être rompu sans modifier le comportement. Michael Feathers identifie plusieurs types de seams : preprocessor seam, object seam, link seam. Object seam est le plus courant : remplacer un objet réel par un stub de test via une interface.
Sprout method et Sprout class — techniques pour ajouter du nouveau code à côté de l’ancien, pas à l’intérieur. Au lieu de modifier une méthode existante, créez une nouvelle méthode avec la logique souhaitée et appelez-la depuis l’ancienne. Cela minimise le risque de casser le code fonctionnel.
class LegacyPaymentProcessor {
def process(payment) {
// 200 lignes de code legacy qui ne doivent pas être touchées
logPayment(payment) // méthode sprout
}
def logPayment(payment) {
// nouveau code ajouté à côté du legacy
}
}
Motif Strangler Fig — l’approche recommandée pour la migration legacy. Un nouveau module est créé en parallèle, le trafic est progressivement redirigé de l’ancien vers le nouveau. L’ancien module meurt naturellement lorsqu’il cesse de recevoir des requêtes. Le motif minimise les risques et permet un rollback en cas de problème.
Branch by Abstraction — technique où une abstraction est créée au-dessus de l’ancienne et de la nouvelle implémentation. Le code client bascule vers l’abstraction et l’ancienne implémentation est progressivement remplacée. Exemple : remplacer la couche réseau d’AFNetworking par Alamofire via un protocole unifié NetworkService.
Migration par étapes — diviser la transition en petites étapes : encapsuler l’ancien module → écrire des tests → créer un nouveau module → exécuter en parallèle → supprimer l’ancien module. Chaque étape se termine par un état stable du système, permettant un déploiement à tout moment.
Foire aux questions
La réécriture complète est l’option la plus risquée. Seulement 25% des projets de Big Rewrite réussissent dans les délais. Il est préférable d’appliquer le motif Strangler Fig : remplacer les modules progressivement sans arrêter le produit. Chaque itération apporte de la valeur métier et les risques sont répartis dans le temps.
Commencez par des tests de caractérisation : exécutez le module sur des données connues, enregistrez le résultat. Golden master testing est un moyen simple de capturer le comportement. Ajoutez des tests chaque fois que vous touchez une ligne de code. Dans 6 mois, vous aurez une structure qui protège contre les régressions.
Si le système est stable, ne nécessite pas de modifications fréquentes et n’affecte pas la vitesse de développement des autres modules — laissez-le. Si ça marche, ne touchez à rien est une approche raisonnable pour les modules legacy isolés à faible fréquence de changements. Ne touchez au code que lorsque des modifications métier sont nécessaires.
Utilisez le versionnement sémantique et mettez à jour par étapes : patch → minor → major. Écrivez des tests de compatibilité pour chaque bibliothèque. Dependabot ou Renovate automatisent la création de PR de mise à jour. Si une bibliothèque est obsolète, planifiez son remplacement via une abstraction.
La dette technique est une métaphore pour estimer le coût des améliorations différées. Le legacy est un système ou un code spécifique qui est déjà devenu obsolète. La dette technique peut s’accumuler en un mois, le legacy prend du temps. Toute dette technique ne devient pas legacy, mais tout legacy contient de la dette technique.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi