widget timeline



Remaniement du code d’un widget de timeline (refactoring)

Durant le processus de création d'une application, le POC (Proof Of Concept) est souvent assemblé à partir de composants déjà existants. Ces composants viennent néanmoins souvent avec une dette technologique. La construction de l’application finale nécessite de faire des choix : utiliser ces composants et accélérer considérablement son développement ou faire table rase et prendre le temps de construire chaque partie.

Cette décision doit être prise en prenant en compte le cahier des charges du client (évolutivité, planning, budget...). Reconstruire chaque partie de l'application aura un impact sur le budget et le temps de réalisation mais simplifiera sa maintenance et son évolution . Dans le cas où le client opte pour l’utilisation de composants existants, l'application pourra rapidement être mise en ligne.

Ce choix implique des contraintes limitant son évolution future et sa maintenance. Faire évoluer un composant indispensable à une application est quelquefois crucial. Lors de la mise à jour de la base NodeJS de la version 18 à la 22, certains composants étaient tellement enracinés dans l'ancienne version qu'il n'était plus possible de les utiliser.

Les prémisses de cette dette technologique se ressentent lors du démarrage de l'application et un message d’avertissement nous indique que le widget utilise une méthode obsolète:

hook.js:608 Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://reactjs.org/link/unsafe-component-lifecycles for details.

* Move data fetching code or side effects to componentDidUpdate.

* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state

* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run npx react-codemod rename-unsafe-lifecycles in your project source folder.

Please update the following components: CustomHeader

Un remaniement du composant est indispensable pour maintenir la compatibilité avec les évolutions futures de la plateforme. Une mise à jour complète demande cependant beaucoup d'efforts et de temps. Comment effectuer l'évolution minimale afin de pouvoir continuer à utiliser le composant ?

Nous avons retenu la stratégie suivante : modifier le widget historique de manière ciblée afin d'effacer la dette technologique et ainsi optimiser le temps de travail requis pour le projet.

Suppression de la dépendance à momentjs

Le widget utilise momentjs pour la gestion et l'affichage du temps. Cette librairie, autrefois très cotée n'est désormais plus maintenue et utilise un concept d'instance dont l’utilisation n’est pas intuitive dans une forme fonctionnelle où sont principalement utilisées des variables immuables.

Le travail consiste à supprimer toutes les références à cette librairie et le cas échéant à la remplacer par une autre plus moderne.

Nous avons choisi date-fns qui fait partie de la recommandation des développeurs de momentjs.

Nous obtenons alors une version du widget totalement indépendante de la librairie obsolète.

Conversion sous forme fonctionnelle

Nous avons commencé l'évolution à partir de chaque widget, en convertissant le code d'origine orienté objet en implémentation fonctionnelle. La méthode utilisée conserve le widget fonctionnel pendant la durée de la conversion, en faisant évoluer chaque composant séparément.

L'application est progressivement convertie dans le nouveau paradigme. Les test unitaires et le mode démo sont utilisés à chaque étape pour confirmer les modifications et qu’elles n'entraînent aucun effet secondaire.

Conversion en Typescript

Quand un composant a été converti avec succès en implémentation fonctionnelle, la conversion est poussée un cran plus loin en utilisant du code Typescript. Sous cette forme, le code est plus facilement maintenable et facilite l'intégration à d'autres systèmes en instaurant un contrôle strict du typage.

Le Typescript impose néanmoins des contraintes pour chaque fonction et variable utilisées dans le composant, obligeant à repenser la structure générale du code. Une déclaration de chaque type utilisé doit être réalise tout en maintenant la compatibilité avec les composants encore non transformés. La conversion en Typescript apporte une plus grande sécurité dans l'utilisation de la librairie. En imposant un type, nous évitons le passage d'arguments erronés et augmentons ainsi la stabilité de l'ensemble.

Conclusion

Cette approche nous a permis de compléter l'application plus rapidement sans pour autant sacrifier son évolutivité future. La complexité du travail a été réduite par la division en petites modifications et par la validation de chaque étape par les tests unitaires et les essais dans la démo.

Le résultat final est un widget entièrement compatible avec la version courante de React et nous libérant de toute dette technologique liée à une version obsolète du code de base.