Langzeitunterstützung für JavaScript-Anwendungen

Wir veröffentlichen eine Übersetzung des Artikels, in der die langfristige Arbeit des Teams zur Erstellung und Pflege eines großen Datenportals in JavaScript ausführlich beschrieben wird.


Im Jahr 2019 wurde ein Artikel über die Wartung großer JavaScript-Anwendungen geschrieben. In Fortsetzung dieses Materials möchten wir ein Kundenprojekt teilen, das mein Team seit 2014 unterstützt.







Datenportal der Organisation für wirtschaftliche Zusammenarbeit und Entwicklung (OECD)





Portal-Homepage



Die Organisation für wirtschaftliche Zusammenarbeit und Entwicklung ist eine zwischenstaatliche Einrichtung, die Daten sammelt und im Auftrag ihrer Mitgliedstaaten Forschungsergebnisse veröffentlicht. Das Portal der Organisation enthält Informationen aus verschiedenen Bereichen: Wirtschaft, Ökologie, Bildung usw.



Das OECD-Datenportal ist das Hauptarchiv für statistische Daten. Es hilft Forschern, Journalisten und politischen Entscheidungsträgern, wichtige Informationen zu finden und sie mithilfe von Diagrammen schnell zu visualisieren. Das OECD-Portal integriert außerdem eine Bibliothek in OECD iLibrary- Veröffentlichungen und eine OECD.Stat- Ressource, in der alle Daten gespeichert sind.



Die OECD wird von Mitgliedstaaten finanziert, dh von Steuerzahlern wie Ihnen und mir. Eine der Anforderungen des Projekts ist die Verwendung kostengünstiger und zuverlässiger Technologien, da die Pflege des Codes für eine lange Zeit wichtig ist.



Das Datenportal ist eine Zusammenarbeit zwischen OECD-Mitarbeitern und externen Entwicklern und Designern. Das ursprüngliche Design und der Prototyp wurden von Moritz Stefaner und dem Raureif-Team erstellt . Und 9elements hat das Front-End-Teil entwickelt und behält es weiterhin bei.



Komplexe JavaScript-Codebasis



Der schwierigste Teil des Frontends auf diesem Portal ist die JavaScript-Diagramm-Engine. Es enthält zehn Hauptdiagrammtypen mit zahlreichen Konfigurationsoptionen. Mithilfe leistungsstarker Schnittstellen können Benutzer die Datenbank abfragen und Diagramme zum Einbetten oder Freigeben erstellen.







Wir haben 2014 mit der Arbeit am Datenportal begonnen. Seitdem wurde nicht viel umgeschrieben, es wurden nur neue Funktionen hinzugefügt, kleine Verbesserungen und Umgestaltungen des Codes. Im Dezember 2020 haben wir dem OECD-Wirtschaftsausblick mehrere neue Funktionen hinzugefügt, darunter vier weitere Diagrammtypen. Diesmal haben wir auch die Codebasis erheblich neu organisiert.



In diesem Artikel werde ich Ihnen zeigen, wie wir es schaffen, den Code so lange zu pflegen und Schritt für Schritt zu verbessern. Ich werde auch verraten, was nicht geklappt hat.



Langweilige Mainstream-Technologie



Das Projekt begann im Jahr 2014 und dann wählten wir einfaches HTML, XSLT-Vorlagen, Sass für Tabellenstile und CoffeeScript als eine Sprache, die mit JavaScript kompiliert wird. Wir haben jQuery, D3, D3.chart und Backbone als JavaScript-Bibliotheken ausgewählt.



Im Jahr 2014 waren diese Technologien die sichersten und interoperabelsten von allen. Die Wahl von CoffeeScript war ein riskantes Spiel. Dank CoffeeScript konnten wir produktiver werden und zuverlässigen Code schreiben. Wir wussten jedoch, dass diese neue Technologie schwierig sein kann.



Seit 2015 das 9elements Team hat begonnen, React für die meisten JavaScript-Webanwendungen zu verwenden. Wir haben darüber nachgedacht, React für eine neue Version der Charting-Engine zu verwenden, aber nicht jeder konnte den richtigen Moment finden. Als Ergebnis stellte sich heraus, dass das Festhalten am ursprünglichen Technologie-Stack die richtige Entscheidung war.



Der soeben beschriebene JavaScript-Stack mag veraltet erscheinen, aber tatsächlich hat die Codebasis den Test der Zeit bestanden. Ein Grund: Die von uns gewählten Technologien sind nach wie vor relevant.



Der zerstörerische Einfluss der Zeit



Viele JavaScript-Bibliotheken sind gekommen und gegangen, aber jQuery ist immer noch die beliebteste. Es ist zuverlässig, gut unterstützt und weit verbreitet. Laut Web Almanac 2020 wird jQuery von 83% aller Websites verwendet. (Im Vergleich dazu wurde React nur bei 4% gefunden.)



Natürlich hat jQuery seine Führungsposition bei der Lösung komplexer DOM-Probleme verloren. Wie bereits erwähnt, würden wir jetzt React oder Preact wählen, um ein solches Datenportal zu erstellen.



Zweite Bibliothek, D3bleibt der Standard für die Datenvisualisierung im Browser. Es besteht seit 2010 und ist immer noch führend. Obwohl einige Hauptversionen die Struktur und API erheblich verändert haben, ist D3 immer noch ein herausragendes Stück Technik.



Die Backbone- Bibliothek ist nicht so beliebt, hat aber ihre Vorteile. Zum Beispiel ist es relativ einfach: Sie können den Quellcode an einem Morgen lesen und die Hauptteile an einem Tag wiederholen. Außerdem wird Backbone weiterhin unterstützt. Es ist voll funktionsfähig, was besonders wichtig ist.



Aus technologischer Sicht ist nur CoffeeScript in der gegenwärtigen Realität keine relevante Technologie. Diese Sprache wurde aufgrund offensichtlicher Mängel in ECMAScript 5 entwickelt. Später wurden viele Ideen von CoffeeScript in die Standards ECMAScript 6 (2015) und ECMAScript 7 (2016) aufgenommen. Von nun an haben wir keinen Grund mehr, es zu benutzen.



Wir haben uns 2014 für CoffeeScript entschieden, weil es die Philosophie "Es ist nur JavaScript" ist. Im Gegensatz zu anderen mit JavaScript kompilierten Sprachen ist CoffeeScript eine einfache Abstraktion. CoffeeScript wird ohne Überraschungen zu reinem JavaScript kompiliert.



Die meisten Unternehmen haben heute ihre Codebasen von CoffeeScript auf modernes JavaScript migriert. Und wir haben das Gleiche getan.



Von CoffeeScript zu TypeScript



Mit diesem Entkoffeinierungswerkzeug haben wir den CoffeeScript-Code in ECMAScript 6 (2015) konvertiert. Wir wollten weiterhin dieselben Browser unterstützen, daher verwenden wir jetzt den Babel-Compiler, um abwärtskompatibles ECMAScript 5 zu erstellen.



Insgesamt verlief der Übergang reibungslos, aber wir wollten hier nicht aufhören.



In neuen Projekten verwenden 9elements-Entwickler TypeScript. Meiner Meinung nach ist TypeScript das Beste, was in der JavaScript-Welt in den letzten Jahren passiert ist. Wie ich in meinem vorherigen Artikel erwähnt habe, lässt TypeScript Sie über Typen nachdenken und lehrt Sie, sie richtig zu benennen.



Für unser Datenportal wollten wir TypeScript nutzen, ohne die Codebasis in vollständig typisiertes TypeScript zu konvertieren.



TypeScript ist eine Obermenge von JavaScript. Der Compiler versteht .js-Dateien gut. Aus diesem Grund haben wir nach und nach Typanmerkungen mithilfe der Technologie von vor 20 Jahren hinzugefügt - JSDOC . Darüber hinaus wurden verschiedene Typen (Typisierungen) in die .ts-Dateien geschrieben, um sie in den JSDOC-Anmerkungen zu referenzieren.



Daher ist die Entwicklungserfahrung in Visual Studio Code ohne großen Aufwand erheblich gewachsen. Während hier keine strikte Typprüfung stattfindet, ist das Bearbeiten des Codes genauso bequem wie in einem normalen TypeScript-Projekt.



Durch die Kombination von langweiliger, aber robuster Technologie mit dem neuesten TypeScript-Compiler konnten wir neue Funktionen und Refactor-Code sicher und einfach hinzufügen.



Dokumentation und Codekommentare



An der Oberfläche ist das Codieren ein Gespräch zwischen Ihnen und dem Computer: Sie sagen dem Computer, was er tun muss.



In Wirklichkeit ist das Codieren jedoch ein Gespräch zwischen Ihnen und dem Leser des Codes. Es ist bekannt, dass Code einmal geschrieben und immer wieder gelesen wird. Zunächst schreiben Sie Code für Ihr zukünftiges Selbst.



Wir haben der Portal-Codebasis viele Kommentare hinzugefügt, und fast alle haben es in den letzten sechs Jahren geschafft, ihren Wert zu beweisen. Offensichtlich sollte der Code so strukturiert sein, dass die Leser ihn besser verstehen. Aber ich glaube nicht an "selbstbeschreibenden" oder "selbstdokumentierenden" Code.



Vor dem Wechsel zu JSDOC haben wir leicht lesbare Typanmerkungen, dokumentierte Funktionsparameter und Rückgabewerte erstellt. Wir haben auch grundlegende Datentypen und komplexe verschachtelte Objektstrukturen dokumentiert.



Diese Kommentare waren sechs Jahre später wirklich hilfreich. Wir haben sie in maschinenlesbare JSDOC- und Typdeklarationen für den TypeScript-Compiler übersetzt.



Dinge brechen - halten Sie immer eine Testsuite bereit



Das Projekt verfügt nur über wenige automatisierte Komponententests und mehr als 50 (!) Testseiten, die alle Portalseiten, Komponenten, Datenabfrageschnittstellen, Diagrammtypen und Einstellungen veranschaulichen. Sie testen sowohl Live- als auch Staging- und Mock-Daten.



Diese Testseiten machen dasselbe wie automatisierte Tests: Wenn wir einen Fehler beheben, fügen wir das Skript zuerst der entsprechenden Testseite hinzu. Wenn wir eine neue Funktion entwickeln, erstellen wir gleichzeitig eine vollständige Testseite.





Testseite



Vor der Freigabe überprüfen wir manuell alle Testseiten und vergleichen sie mit dem letzten sowohl optisch als auch funktionell. Dies ist zeitaufwändig, ermöglicht es Ihnen jedoch, Regressionen schnell zu finden.



Ich denke nicht, dass eine automatisierte Testsuite effizienter wäre. Es ist nahezu unmöglich, interaktive Datenvisualisierungen in einem Browser automatisch zu testen. Visuelle Regressionstests sind ein wertvolles Werkzeug, aber in unserem Fall können zu viele falsche Fehler auftreten.



Abwärts- und Vorwärtskompatibilität



2014 sollte unser Portal mit Internet Explorer 9 funktionieren. Jetzt ist Internet Explorer nicht mehr so ​​wichtig, insbesondere beim Erstellen einer dynamischen Engine zum Plotten im Browser.



Wir haben uns jedoch entschlossen, die Kompatibilität mit älteren Browsern beizubehalten. Das Datenportal ist eine internationale Plattform, die Benutzer aus aller Welt besuchen. Nicht jeder hat die neuesten Computer und neuen Browser.





Portal in Internet Explorer 9



Durch den Einsatz langweiliger Standardtechnologien konnten wir ein grundlegendes Maß an Browserunterstützung aufrechterhalten. Natürlich gibt es auch einige moderne Webfunktionen, aber wir aktivieren sie nur, wenn der Browser dies unterstützt. Hier hilft uns der Progressive Enhancement- Ansatz. (fortschreitende Verbesserung). Wir verwenden auch Babel und Polyfills, damit moderne JavaScript-Funktionen in älteren Browsern funktionieren.



Ihre Abstraktionen könnten beißen



Im Laufe der Jahre waren wir nicht durch den Technologie-Stack eingeschränkt. Vielmehr standen ihre eigenen Abstraktionen im Weg.



Wir haben die Benutzeroberfläche in visuelle Teile (Ansichten) aufgeteilt und eine Basisklasse ähnlich wie Backbone.View erstellt. (Heutzutage verwenden alle großen JavaScript-Bibliotheken den Begriff "Komponente" anstelle von "Ansicht" für Teile der Benutzeroberfläche.) Wir haben Backbone.Model zum Speichern von Daten und Status verwendet. Es hat super funktioniert, aber wir haben uns entschlossen, an unseren eigenen Best Practices festzuhalten.



Die Idee hinter der Aufteilung der Backbone-Modellansicht ist, dass dieses Modell die einzige Quelle der Wahrheit ist. Das DOM sollte nur die Modelldaten widerspiegeln. Alle Änderungen müssen auch vom Modell stammen. Moderne Frameworks wie React, Vue und Angular folgen der Konvention, dass die Benutzeroberfläche eine "Statusfunktion" ist, was bedeutet, dass die Benutzeroberfläche definitiv vom Status abgeleitet ist.



Wir haben gegen dieses Prinzip verstoßen und manchmal das DOM zur Quelle der Wahrheit gemacht. Dies führte zu Verwechslungen mit dem Code, der das Modell als maßgebliche Quelle ansah.



Objektorientierte Diagramme



Für Diagramme haben wir einen anderen Ansatz gewählt: Wir haben Diagrammklassen erstellt, die sich von den oben beschriebenen unterscheiden.



Der D3 selbst ist funktionsfähig. Ein Diagramm wird normalerweise mit einer Renderfunktion erstellt und aktualisiert, die andere Funktionen aufruft. Diese Diagramme sind eine Einführung in diese großartige Funktion. In bestimmten Objekten ist mehr Status enthalten.



Dies macht D3 ausdrucksstark und flexibel. Der D3-Code ist jedoch schwer zu lesen, da es nur wenige Konventionen (Konventionen, die nicht dokumentiert sind) für den Umgang mit Diagrammstrukturen gibt.



Irene Ros und Mike Pennisi, Entwickler bei Bocoup, erfanden d3.chart, eine kleine Bibliothek über D3, die klassenbasiertes OOP darstellt. Das Hauptziel war die Strukturierung und Wiederverwendung von Diagrammcode. Diese Diagramme bestehen aus Ebenen, von denen jede einen bestimmten Teil des DOM mithilfe von D3 rendert und aktualisiert. Darüber hinaus können andere Diagramme an Diagramme angehängt werden.



Die allgemeine Regel von OOP lautet: "Zusammensetzung hat Vorrang vor Vererbung." Leider haben wir für das Verhalten des Diagramms eine seltsame Kombination aus Zusammensetzung und Vererbung gewählt.



Wir mussten Funktionen oder einfache Klassen anstelle komplexer Klassenhierarchien verwenden. Die Leute wickeln D3 immer noch in klassenbasiertes OOP ein, aber keine klassenbasierte Lösung konnte die funktionale Struktur von D3 übertreffen.



Fassen wir zusammen



Seit wir 2014 den Front-End-Teil des Datenportals entwickelt haben, gibt es viele coole Ansätze zum Erstellen von JavaScript-basierten Webschnittstellen.



Jetzt sind UI-Komponenten deklarativ. Sie können auf das Rendern von HTML-Vorlagen und das manuelle Aktualisieren des DOM verzichten. Sie aktualisieren nur den Status und das Framework aktualisiert das DOM. Dieser unidirektionale Datenfluss eliminiert eine ganze Klasse von Fehlern.



Die Technologien, die wir 2014 ausgewählt haben, haben sich entweder bewährt oder den Wechsel zu einem anderen Stack erleichtert. Sie mögen denken, dass wir Glück hatten, aber wir haben uns bewusst für dauerhafte Technologien entschieden.



Bei 9elements versuchen wir immer, moderne Technologien zu verwenden, einschließlich der Bewertung experimenteller Front-End-Technologien, die in 3-4 Jahren möglicherweise nicht relevant sind. Leider können viele Open-Source-JavaScript-Projekte technisch fortschrittlich, aber instabil sein.



Für jedes Projekt suchen wir das optimale Gleichgewicht zwischen nachhaltigen Technologien mit minimalen Risiken und einem innovativen Stack, der uns hilft, ein Qualitätsprodukt zu schaffen.



All Articles