Prise en charge à long terme des applications JavaScript

Nous publions une traduction de l'article, qui décrit en détail le travail à long terme de l'équipe pour créer et maintenir un grand portail de données en JavaScript.


En 2019, un article a été écrit sur la maintenance de grandes applications JavaScript. Dans la continuité de ce matériel, nous souhaitons partager un projet client que mon équipe accompagne depuis 2014.







Portail de données de l'Organisation de coopération et de développement économiques (OCDE)





Page d'accueil du portail



L'Organisation de coopération et de développement économiques est un organisme intergouvernemental qui collecte des données et publie des recherches au nom de ses États membres. Le portail de l'organisation contient des informations dans divers domaines: économie, écologie, éducation, etc.



Le portail de données de l'OCDE est le principal référentiel de données statistiques. Il aide les chercheurs, les journalistes et les décideurs à trouver des informations importantes et à les visualiser rapidement à l'aide de diagrammes. Le portail de l'OCDE intègre également une bibliothèque avec les publications de l' OCDE iLibrary et une ressource OECD.Stat où toutes les données sont stockées.



L'OCDE est financée par les États membres, c'est-à-dire par des contribuables comme vous et moi. L'une des exigences du projet est d'utiliser des technologies rentables et fiables, car la maintenance du code est importante pendant longtemps.



Le portail de données est une collaboration entre le personnel de l'OCDE et des développeurs et concepteurs externes. La conception initiale et le prototype ont été créés par Moritz Stefaner et l'équipe Raureif . Et 9elements a développé la partie frontale et la maintient toujours.



Base de code JavaScript complexe



La partie la plus difficile de l'interface sur ce portail est le moteur de création de graphiques JavaScript. Il contient dix principaux types de graphiques avec de nombreuses options de configuration. À l'aide d'interfaces puissantes, les utilisateurs peuvent interroger la base de données et créer des diagrammes à incorporer ou à partager.







Nous avons commencé à travailler sur le portail de données en 2014. Depuis, il n'a pas été beaucoup réécrit, seules de nouvelles fonctionnalités ont été ajoutées, de petites améliorations et refactorisations du code. En décembre 2020, nous avons ajouté plusieurs nouvelles fonctionnalités au rapport Perspectives économiques de l' OCDE , dont quatre autres types de graphiques. Nous avons également réorganisé considérablement la base de code cette fois-ci.



Dans cet article, je vais vous montrer comment nous parvenons à maintenir le code aussi longtemps et à l'améliorer étape par étape. Je vais également révéler ce qui n'a pas fonctionné.



Technologie grand public ennuyeuse



Le projet a débuté en 2014 et c'est à ce moment-là que nous avons choisi le HTML simple, les modèles XSLT, Sass pour les styles de tableau et CoffeeScript comme langage qui compile avec JavaScript. Nous avons choisi jQuery, D3, D3.chart et Backbone comme bibliothèques JavaScript.



En 2014, ces technologies étaient les plus sûres et les plus interopérables, de toutes, choisir CoffeeScript était un pari risqué. Grâce à CoffeeScript, nous avons pu devenir plus productifs et avoir écrit du code fiable. Mais nous savions que cette nouvelle technologie pouvait être difficile.



Depuis 2015, l'équipe 9elementsa commencé à utiliser React pour la plupart des applications Web JavaScript. Nous avons pensé utiliser React pour une nouvelle version du moteur de cartographie, mais tout le monde n'a pas trouvé le bon moment. En conséquence, il s'est avéré que s'en tenir à la pile technologique d'origine était la bonne décision.



La pile JavaScript qui vient d'être décrite peut sembler obsolète, mais en fait, la base de code a résisté à l'épreuve du temps. Une raison: les technologies que nous avons choisies sont toujours d'actualité.



L'influence destructrice du temps



De nombreuses bibliothèques JavaScript sont venues et disparues, mais jQuery est toujours la plus populaire. Il est fiable, bien pris en charge et répandu. Selon Web Almanac 2020 , jQuery est utilisé par 83% de tous les sites Web. (En comparaison, React n'a été trouvé qu'à 4%.)



Bien sûr, jQuery a perdu sa position de leader dans la résolution de problèmes DOM complexes. Comme mentionné, pour le moment, nous choisirions React ou Preact pour créer un tel portail de données.



Deuxième bibliothèque, D3reste la norme pour la visualisation des données dans le navigateur. Il existe depuis 2010 et en est toujours le leader. Bien que quelques versions majeures aient considérablement modifié la structure et l'API, D3 reste une pièce d'ingénierie exceptionnelle.



La bibliothèque Backbone n'est pas si populaire, mais elle a ses avantages. Par exemple, c'est relativement simple: vous pouvez lire le code source en une matinée et refaire les parties principales en une journée. De plus, Backbone est toujours pris en charge. Il est entièrement fonctionnel, ce qui est particulièrement important.



D'un point de vue technologique, seul CoffeeScript n'est pas une technologie pertinente dans les réalités actuelles. Ce langage a été développé en raison de failles évidentes dans ECMAScript 5. Plus tard, de nombreuses idées de CoffeeScript ont été incorporées dans les normes ECMAScript 6 (2015) et ECMAScript 7 (2016). Désormais, nous n'avons aucune raison de l'utiliser.



Nous avons choisi CoffeeScript en 2014 en raison de sa philosophie «C'est juste du JavaScript». Contrairement à d'autres langages compilés avec JavaScript, CoffeeScript est une abstraction simple. CoffeeScript compile en JavaScript pur sans surprise.



Aujourd'hui, la plupart des entreprises ont migré leurs bases de code de CoffeeScript vers JavaScript moderne. Et nous avons fait de même.



De CoffeeScript à TypeScript



Avec cet outil de décaféination , nous avons converti le code CoffeeScript en ECMAScript 6 (2015). Nous voulions continuer à supporter les mêmes navigateurs, donc nous utilisons maintenant le compilateur Babel pour créer ECMAScript 5.



Dans l'ensemble, la transition s'est bien déroulée, mais nous ne voulions pas nous arrêter là.



Dans les nouveaux projets, les développeurs de 9elements utilisent TypeScript. À mon avis, TypeScript est la meilleure chose qui se soit produite dans le monde JavaScript au cours des deux dernières années. Comme je l'ai mentionné dans mon article précédent, TypeScript vous fait réfléchir aux types et vous apprend à les nommer correctement.



Pour notre portail de données, nous allions tirer parti de TypeScript sans convertir la base de code en TypeScript entièrement typé.



TypeScript est un sur-ensemble de JavaScript. Le compilateur comprend bien les fichiers .js. Par conséquent, nous avons progressivement ajouté des annotations de type à l'aide de la technologie d'il y a 20 ans - JSDOC . En plus de cela, plusieurs types (typages) ont été écrits dans les fichiers .ts pour les référencer dans les annotations JSDOC.



Ainsi, l'expérience de développement dans Visual Studio Code s'est considérablement développée sans trop d'efforts. Bien qu'il n'y ait pas de vérification de type stricte ici, l'édition du code est tout aussi pratique que dans un projet TypeScript normal.



En combinant une technologie plutôt ennuyeuse mais robuste avec le dernier compilateur TypeScript, nous avons pu ajouter de nouvelles fonctionnalités et refactoriser le code en toute sécurité et facilement.



Commentaires sur la documentation et le code



En apparence, le codage est une conversation entre vous et l'ordinateur: vous dites à l'ordinateur ce qu'il doit faire.



Mais, en réalité, le codage est une conversation entre vous et le lecteur du code. Il est bien connu que le code est écrit une fois et lu encore et encore. Tout d'abord, vous écrivez du code pour votre futur moi.



Nous avons ajouté de nombreux commentaires à la base de code du portail, et presque tous ont réussi à prouver leur valeur au cours des six dernières années. De toute évidence, le code doit être structuré de manière à aider les lecteurs à le comprendre. Mais je ne crois pas au code «auto-descriptif» ou «auto-documenté».



Avant de passer à JSDOC, nous avons créé des annotations de type faciles à lire, des paramètres de fonction documentés et des valeurs de retour. Nous avons également documenté les types de données de base et les structures d'objets imbriqués complexes.



Ces commentaires ont été vraiment utiles six ans plus tard. Nous les avons traduits en JSDOC lisible par machine et en déclarations de type pour le compilateur TypeScript.



Les choses se cassent - ayez toujours une suite de tests à portée de main



Le projet ne comporte que quelques tests unitaires automatisés et plus de 50 (!) Pages de test qui présentent toutes les pages du portail, les composants, les interfaces de requête de données, les types de graphiques et les paramètres. Ils testent à la fois des données en direct, de mise en scène et de simulation.



Ces pages de test font la même chose que les tests automatisés: si nous corrigeons un bogue, nous ajoutons d'abord le script à la page de test correspondante. Si nous développons une nouvelle fonctionnalité, nous créons en même temps une page de test complète.





Page de test



Avant la publication, nous vérifions manuellement toutes les pages de test et les comparons à la dernière à la fois visuellement et fonctionnellement. Cela prend du temps, mais vous permet de trouver rapidement des régressions.



Je ne pense pas qu'une suite de tests automatisés serait plus efficace. Il est presque impossible de tester automatiquement les visualisations de données interactives dans un navigateur. Les tests de régression visuelle sont un outil précieux, mais dans notre cas, ils peuvent donner trop de fausses erreurs.



Compatibilité ascendante et ascendante



En 2014, notre portail était censé fonctionner avec Internet Explorer 9. Désormais, Internet Explorer n'est plus si important, en particulier lors de la création d'un moteur dynamique de traçage dans le navigateur.



Cependant, nous avons décidé de conserver la compatibilité avec les anciens navigateurs. Le portail de données est une plate-forme internationale où les utilisateurs du monde entier visitent. Tout le monde n'a pas les derniers ordinateurs et les nouveaux navigateurs.





Portail dans Internet Explorer 9



Nous avons pu maintenir un niveau de base de support de navigateur en utilisant des technologies standard ennuyeuses. Bien sûr, il existe également quelques fonctionnalités Web modernes, mais nous ne les activons que si le navigateur le prend en charge. C'est là que l'approche Progressive Enhancement nous aide. (amélioration progressive). Nous utilisons également Babel et polyfills pour faire fonctionner les fonctions JavaScript modernes dans les anciens navigateurs.



Vos abstractions pourraient mordre



Au fil des ans, nous n'avons pas été limités par la pile technologique. Au contraire, leurs propres abstractions faisaient obstacle.



Nous avons divisé l'interface utilisateur en parties visuelles (vues) et créé une classe de base similaire à Backbone.View. (Aujourd'hui, toutes les grandes bibliothèques JavaScript utilisent le terme «composant» au lieu de «vue» pour certaines parties de l'interface utilisateur.) Nous avons utilisé Backbone.Model pour stocker les données et l'état. Cela a très bien fonctionné, mais nous avons décidé de nous en tenir à nos propres meilleures pratiques.



L'idée derrière la division de la vue du modèle Backbone est que ce modèle est la seule source de vérité. Le DOM doit simplement refléter les données du modèle. Toutes les modifications doivent également provenir du modèle. Les frameworks modernes tels que React, Vue et Angular suivent la convention selon laquelle l'interface utilisateur est une «fonction d'état», ce qui signifie que l'interface utilisateur est définitivement dérivée de l'état.



Nous avons violé ce principe et parfois fait du DOM la source de la vérité. Cela a conduit à une confusion avec le code qui considérait le modèle comme une source faisant autorité.



Graphiques orientés objet



Pour les graphiques, nous avons adopté une approche différente: nous avons créé des classes de graphiques différentes de celles décrites ci-dessus.



Le D3 lui-même est fonctionnel. Un graphique est généralement créé et mis à jour avec une fonction de rendu qui appelle d'autres fonctions. Ces diagrammes sont une introduction à cette fonctionnalité intéressante. Plus d'état est contenu dans des objets spécifiques.



Cela rend D3 expressif et flexible. Mais le code D3 est difficile à lire car il existe peu de conventions (conventions qui ne sont pas documentées) pour traiter les structures de graphique.



Irene Ros et Mike Pennisi, développeurs chez Bocoup, ont inventé d3.chart, une petite bibliothèque au-dessus de D3 qui représente la POO basée sur les classes. Son objectif principal était de structurer et de réutiliser le code graphique. Ces diagrammes sont constitués de couches, dont chacune rend et met à jour une partie spécifique du DOM à l'aide de D3. De plus, d'autres diagrammes peuvent être joints aux graphiques.



La règle générale de la POO est «La composition prévaut sur l'héritage». Malheureusement, nous avons choisi une étrange combinaison de composition et d'héritage pour le comportement du diagramme.



Nous devions utiliser des fonctions ou des classes simples au lieu de hiérarchies de classes complexes. Les gens encapsulent toujours D3 dans la POO basée sur les classes, mais aucune solution basée sur les classes n'a été en mesure de surpasser la structure fonctionnelle de D3.



Résumons



Depuis que nous avons développé la partie frontale du portail de données en 2014, il existe de nombreuses approches intéressantes pour créer des interfaces Web basées sur JavaScript.



Désormais, les composants de l'interface utilisateur sont déclaratifs, vous pouvez vous passer du rendu des modèles HTML et de la mise à jour manuelle du DOM. Vous venez de mettre à jour l'état et le framework met à jour le DOM. Ce flux de données unidirectionnel élimine toute une classe de bogues.



Les technologies que nous avons choisies en 2014 ont résisté à l'épreuve du temps ou ont facilité le passage à une autre pile. Vous pourriez penser que nous avons eu de la chance, mais nous avons délibérément fait un choix en faveur des technologies durables.



Chez 9elements, nous essayons toujours d'utiliser des technologies modernes, y compris en évaluant des technologies frontales expérimentales qui peuvent ne pas être pertinentes dans 3-4 ans. Malheureusement, de nombreux projets JavaScript open source peuvent être techniquement progressifs, mais instables.



Pour chaque projet, nous recherchons l'équilibre optimal entre des technologies durables avec un minimum de risques et une pile innovante, qui nous aide à créer un produit de qualité.



All Articles