Pour moderniser une application existante, commencez par écrire pourquoi elle doit changer, puis évaluez ensemble le code et la production. Stabilisez le système et placez des tests autour du comportement dont le métier dépend avant d'en modifier la structure. Avec ce filet de sécurité, remplacez le système pièce par pièce, migrez les données de façon délibérée, et gardez la réécriture complète pour le cas rare où presque rien ne mérite d'être conservé.
Nommez la raison métier avant de toucher au code
Moderniser coûte cher, alors commencez par la raison. Les plus courantes : un environnement d'exécution ou un framework en fin de vie, des changements qui prennent des semaines parce que chaque mise en production casse quelque chose, un système qu'une seule personne comprend, ou une plateforme incapable de porter ce dont le métier a besoin ensuite. Chaque raison mène à une première étape différente.
Écrivez cette raison avec une mesure que vous pourrez vérifier plus tard, comme la fréquence des mises en production, le nombre d'incidents ou le temps qu'il faut à un changement courant pour arriver aux utilisateurs. Sans elle, la modernisation devient un projet technique sans fin, difficile à défendre lors de la prochaine revue budgétaire.
Évaluez le code et la production avant de décider quoi que ce soit
Une évaluation vous dit ce que vous avez réellement. Gardez-la courte et faites-la aboutir à un rapport écrit et à une première étape recommandée. Lisez le code, mais lisez aussi la production : journaux, incidents, requêtes lentes et façon dont les mises en production sont faites. Les pires problèmes se trouvent souvent autour du code plutôt que dedans.
- Les versions de l'environnement d'exécution, du framework et des bibliothèques, et celles qui ne reçoivent plus de correctifs de sécurité
- Les parties qui changent le plus souvent et celles qui cassent le plus souvent, d'après l'historique des versions et le journal des incidents
- La couverture de tests sur les parcours dont dépend le métier
- La façon dont l'application est construite, configurée et déployée, et qui sait le faire
- Le modèle de données, son volume, et les autres systèmes qui lisent ou écrivent dans la même base
- Les personnes qui connaissent le système, et ce qu'elles seules savent
Stabilisez d'abord la production pour travailler sur une base solide
Si le système tombe chaque semaine, la modernisation sera interrompue chaque semaine. Corrigez d'abord ce qui provoque les incidents : ajoutez supervision et alertes sur les parcours critiques, automatisez la construction et le déploiement pour que les mises en production soient reproductibles, et sortez les secrets et la configuration du code.
Ces étapes rapportent tout de suite et rendent chaque étape suivante plus sûre. Elles montrent aussi très tôt si l'équipe peut modifier le système sans le casser, ce qu'il vaut mieux savoir avant de s'engager dans un plan plus large.
Posez un filet de tests autour du comportement dont vous dépendez
Le code existant a généralement peu de tests, et son comportement documenté correspond rarement à son comportement réel. Avant de changer la structure, écrivez des tests de caractérisation : des tests qui enregistrent ce que fait le système aujourd'hui, y compris ses cas limites étranges, pour que tout changement de comportement apparaisse comme un test en échec.
Commencez par les bords, avec des tests qui appellent l'application par son API ou son interface et vérifient les résultats, car ils survivent aux changements internes. Pour les calculs et les rapports, rejouez des entrées réelles dans l'ancien et le nouveau code et comparez les sorties. Ajoutez des tests plus fins à chaque partie au fur et à mesure que vous la restructurez. Notre article sur la mise à niveau d'une application Java 8 critique montre le même filet de sécurité appliqué à une montée de version.
Remplacez le système pièce par pièce au lieu de le réécrire
Une réécriture complète paraît propre sur le papier, mais l'ancien système continue de tourner et d'évoluer pendant que le nouveau rattrape son retard, et chaque comportement non documenté doit être redécouvert en chemin. C'est pourquoi les réécritures prennent si souvent plus de temps que prévu, pendant que le métier attend.
L'alternative habituelle est le pattern strangler fig (« figuier étrangleur »). Placez une couche de routage, comme un reverse proxy ou une passerelle d'API, devant l'application existante. Construisez une fonctionnalité à la fois dans le nouveau code, et envoyez-lui le trafic de cette fonctionnalité une fois qu'elle a fait ses preuves. L'ancien système se réduit jusqu'à pouvoir être éteint, et le métier en tire de la valeur à chaque étape.
Une réécriture peut rester le bon choix : quand la base de code est petite et son comportement bien compris, ou quand la plateforme sur laquelle elle tourne ne peut pas être maintenue assez longtemps pour un remplacement progressif. Décidez avec des critères écrits, pas sous le coup de la frustration.
Traitez les données comme une migration à part entière
Le code peut être remplacé par tranches ; les données se découpent plus difficilement. Tant que l'ancien et le nouveau code partagent une base de données, chaque changement de schéma doit être coordonné. Décidez tôt quel système fait référence pour chaque type de données, et évitez que deux systèmes écrivent le même enregistrement sans règle pour savoir quelle écriture l'emporte.
Quand une fonctionnalité est déplacée, migrez ou synchronisez ses données de façon délibérée : des scripts de migration testés sur une copie de la production, ou une synchronisation continue tant que les deux systèmes tournent. Prévoyez comment vous réconcilierez les deux, par exemple avec des comptages et des sommes de contrôle quotidiens, et gardez la possibilité de revenir en arrière tant que les chiffres ne concordent pas.
Ordonnez le travail par risque et par valeur, et montrez vite des progrès
Organisez le travail pour que chaque étape réduise un risque ou apporte quelque chose que le métier peut voir. Un enchaînement courant consiste à stabiliser et automatiser, ajouter des tests, mettre à niveau l'environnement d'exécution, puis extraire les fonctionnalités qui changent le plus souvent. Les parties stables et rarement modifiées peuvent attendre, parfois indéfiniment.
Gardez un plan court et revoyez-le après chaque étape, car ce que vous apprenez changera l'ordre. Nos ingénieurs ont travaillé ainsi sur des systèmes critiques. Via Sopra Steria, ils ont mené la migration de Java 8 à 16 d'une application critique de trading journalier de gaz, et au sein de l'équipe du programme cloud du Crédit Agricole, nous avons évalué chaque application que nous avons migrée pour décider s'il fallait la mettre à niveau ou la reconstruire. Si vous voulez une évaluation de votre propre système, ou une équipe pour mener le plan, SDK Enterprises fait les deux sous un seul contrat.
À retenir
- Écrivez la raison métier de la modernisation, avec une mesure que vous pourrez vérifier plus tard.
- Évaluez le code et la production ensemble avant de choisir entre mise à niveau, remplacement progressif et réécriture.
- Stabilisez la production et placez des tests de caractérisation autour du comportement critique avant de changer la structure.
- Remplacez le système pièce par pièce derrière une couche de routage, sauf si une réécriture est clairement plus petite et plus sûre.
- Planifiez la propriété, la synchronisation et la réconciliation des données comme une migration à part entière.
FAQ
Faut-il réécrire notre application existante de zéro ?
En général, non. Une réécriture court après un système qui continue d'évoluer et doit redécouvrir un comportement que personne n'a documenté. Remplacez-le progressivement, sauf si la base de code est petite et bien comprise, ou liée à une plateforme qui ne peut pas être maintenue en service.
Combien de temps faut-il pour moderniser une application existante ?
Cela dépend de la taille du système, de sa couverture de tests, de l'enchevêtrement de ses données et de l'ampleur des changements. Une évaluation courte vous donne un plan réaliste et une première étape assez petite pour être terminée et mesurée, plutôt qu'une seule date pour l'ensemble.
Peut-on continuer à livrer des fonctionnalités pendant la modernisation ?
Oui, et c'est même souhaitable. Le remplacement progressif permet à l'équipe de livrer des fonctionnalités dans le nouveau code pendant que le système existant continue de tourner. Convenez de la part du temps de l'équipe consacrée à la modernisation, pour que les fonctionnalités ne l'absorbent pas en silence.