Restructurer un legacy : comment et pourquoi - Compte-rendu du talk de Marc Bojoly à La Duck Conf 2019
La Genèse
Tout commence avec la lecture d'un article de blog des années 2000 : comme programmeur ou architecte, on aime bien partir d'un terrain vide, faire « tabula rasa » de l’existant, pour construire comme on se l'imagine dans notre esprit.
Il est plus dur de lire un programme info que de l'écrire (jaelonsofware). Il faut entrer dans la logique du programmeur et poursuivre le développement selon les principes qu’il a choisi.
Cependant, l’exemple de Netscape montre que vouloir tout réécrire from scratch peut être une des pires stratégies.
Face à un marché qui propose de nouvelles fonctionnalités très rapidement, l’organisation qui veut refondre son legacy et veut repartir de zéro ne parviendra pas à enrichir son système avec de nouvelles fonctionnalités au même rythme que la concurrence.
Le contexte
Nous parlons d’une société spécialisée dans le traitement des sinistres en assurance (habitat, responsabilité civile) qui a acquis deux autres sociétés spécialisées dans le traitement des sinistres en assurance construction.
Dans le domaine du traitement des sinistres les marges sont faibles, donc les contraintes sur le budget informatique sont fortes. Elles viennent s’ajouter à des contraintes planning : il faut ajouter rapidement de nouvelles fonctionnalités au système existant, pour répondre aux besoins des clients, tout en développant le nouveau système.
L’objectif était de refondre les systèmes des trois sociétés qui fusionnent pour ne conserver qu’un seul système, afin de faire des économies sur la maintenance et mettre à disposition les nouveautés à tous les employés (ce qui permettra aux employés des trois entreprises de s’entraider).
L’état du SI
Nous sommes partis de trois applications existantes qui reflètent bien l’histoire de l’informatique des années 90 à nos jours.
Il y a tout d’abord le SI cœur de métier du client : construit en 2013 il repose sur un progiciel fortement personnalisé, (2,5M de lignes de code spécifique), et on peut constater un manque de connaissance du système dans son ensemble avec des erreurs de compréhension
On trouve ensuite une application issue du rachat de la 1ere société : construite dans les 90's, selon une architecture client serveur, avec serveur (dans le bureau). Le décommissionnement de cette application avait été démarré, sans aboutir.
Et enfin, une troisième application : 3e application écrite depuis le début des années 2000 en VB .NET par un seul développeur.
Allez, on se retrousse les manches...
L’idée initiale face à ce constat était de repartir de 0. Mais avant tout, il fallait regarder quelque chose : l’existant.
En essayant de positionner dessus ce dont on a besoin pour décrire le métier nous nous sommes rendus compte qu’il ne manquait que peu de choses (assez ciblé).
- Un référentiel des intervenants
- Une gestion des police de construction
- Des traitements différenciés en fonction des clients
C’est entre 20 et 30% de code à ajouter ou faire évoluer. Conclusion : Il faut restructurer le legacy plutôt que repartir from scratch.
Qu'est-ce qu'un legacy ?
Un legacy c’est un logiciel qui utilise des techniques obsolètes, difficile à prendre en main, dont la connaissance est faible voire erronée, et dans lequel on a plus confiance.
Pour faire un parallèle, on pourrait citer l’exemple de la tour First. Elle a été déshabillée et a été exhaussée de 10 étages.
- Lire et comprendre le code pour savoir où on va s'insérer. C’est moins coûteux (Il faudrait 3x plus de budget pour réécrire from scratch). que tout redévelopper, même si c’est plus pénible.
- Refactorer le code par petites touches (c’est indispensable pour prendre en main le logiciel et donner une vision d'avenir).
Ok, comment on fait ?
On utilise une méthode de « Clean architecture » :
- On crée une 2nde arborescence de paquets.
- Au fur et à mesure des évolutions on refactore le code et ou le déplace dans la nouvelle arborescence.
Voir la présentation complète sur slideshare
Ce qu’il faut prendre en compte : Il y a un budget désendettement (10% du budget total) et la vélocité est plus faible qu'un projet normal.
On initialise une meilleure documentation du nouveau code. La documentation, c’est - en général non exhaustive, long à lire, pas à jour.
Pour être utile, la documentation doit dire pourquoi on a fait certains choix et comment se repérer dans le code. Cela peut se matérialiser par des markdown dans le contrôle de source. La documentation est considérée comme du code : on la fait réviser par toute l'équipe, elle est facile à trouver dans le code, elle est facile à gérer en configuration (on peut comparer la date des commits de la documentation à la date des commits du code correspondant).
Le concept du LADR (« Lightweight architecture decision record ») permet d’assurer une documentation légère, tout en étant utile et facile à maintenir.
On accepte que la documentation ne soit pas exhaustive. En fait c’est une succession de décisions d'architecture. Le LADR mentionne ces décisions (pourquoi on fait les choix).
On y note (par ordre d’importance) :
- La décision ;
- Le contexte qui explique le cadre ;
- Les décisions amendées ;
- Les discussions qui ont conduit à cette décision.
Et aujourd’hui ?
On est au milieu du gué mais il y a des signaux positif s :certaines classes commencent à être réutilisées. Au bout d'un an, des développeurs vont lire la documentation et la compléter (notamment avec le départ de certaines personnes). C'est un des avantages du LADR : il permet de faciliter la mise à jour.
Comment ne pas refaire un legacy ? L’équipe a conscience que ce qui se fait aujourd’hui sera considéré comme du legacy dans plusieurs années.
Il faut retenir 4 caractéristiques :
- La technologie n'est pas la solution. C'est un outil pour répondre à un besoin. Il ne s'agit pas d'utiliser la dernière techno à la mode ;
- Il faut simplifier ;
- Il faut documenter l'intention pour faciliter la prise en main (comprendre le WHY d'une décision) ;
- Il faut saisir les opportunités qui se présentent.
Comment ne pas apporter de la complexité ?
Parfois la technologie seule ne permettra pas de simplifier la complexité.
Exemple : le syndrome du “+1 flux”. Dès qu’un nouveau besoin métier émerge, on rajoute un nouveau flux. Or rajouter un flux supplémentaire, c’est accroître la complexité.
Et si on passait de Talend à de l'API ? En fait cel reste un flux, c’est seulement l’expression du besoin d’un nouvelle donnée ce qui - de fait - ajoute de la complexité.
On utilisera ici plutôt qu’un changement de technologie un pattern classique, celui de la façade.
On isole l'ensemble des trois applications derrière une façade. L'extranet ne dialogue qu'avec l'application X au lieu de trois applications pour manipuler quelque chose de plus simple.
Ici, le découpage en micro-service n’est pas possible car le workflow rajoute de l'information à chaque étape dans le même ensemble de tables. On peut malgré tout essayer d'éviter de rajouter de la complexité à l'existant. Par exemple lorsqu’il s’agit d’établir le lien avec une nouvelle API cliente on pourrait le réaliser dans l’application. Mais la mise en oeuvre d’un pattern royaume émissaire en sortant la complexité d’intégration semble ici pour opportune.
Conclusion : Il faut saisir les opportunités. Dès qu’un nouveau besoin d'évolution métier émerge, on en profite pour introduire les évolutions sur la structure de l'application.
Dernier exemple : la partie mobile du système permet de saisir des données via des formulaires pdf. A la migration vers une nouvelle technologie la première idée est de développer de nouveaux écrans sur l'application mobile et sur l'application métier.
Les utilisateurs sont habitués à avoir une IHM différente pour les deux canaux. Les écrans sont développés peuvent être développés dans une nouvelle application, reposant sur un stack plus moderne qui pourra reprendre progressivement la complexité du legacy.
Conclusion : Comment intégrer la nouvelle application à l'existant ? En s’intégrant par l'IHM et par les données.
Take Away
- Refactorer par petites touches de manière opportuniste
- Documenter les choix pour rendre plus facile la prise en main du code et le mettre en oeuvre
- Ne pas céder aux sirènes de la technologie (cela laisse du legacy pour les successeurs)
- Construire en dehors du legacy quand c'est pertinent
- Saisir les opportunités des évolutions métier pour construire l'avenir