© MarcoVector/Shutterstock.com
Gestatten, Node.js – Teil 3

Codequalität mit Node.js


Wichtig bei der Entwicklung mit Node.js ist nicht nur das Schreiben des eigentlichen Codes, sondern auch die Qualitätssicherung. Dazu zählen neben der gewissenhaften Strukturierung des Codes auch das Anwenden von Coderichtlinien und das Ausführen von automatisierten Tests.

Im zweiten Teil dieser Serie ist eine in Node.js geschriebene Anwendung entstanden, die ein API zum Verwalten einer einfachen Aufgabenliste zur Verfügung stellt. Das API arbeitet dabei bewusst nicht nach REST, sondern trennt lediglich das Schreiben vom Lesen. Schreibende Vorgänge basieren auf POST, lesende auf GET.

Die eigentliche Semantik wurde dabei in den Pfad des URL verlagert, sodass die fachliche Intention erhalten bleibt und das API weitaus besser verständlich ist, als wenn es lediglich auf die vier in REST vorgesehenen technischen Verben setzen würde. Die aktuelle Ausbaustufe der Anwendung enthält drei Routen, auf der einen Seite zum Notieren und Abhaken von Aufgaben, andererseits zum Auflisten aller unerledigten Aufgaben:

  • POST /note-todo

  • POST /tick-off-todo

  • GET /pending-todos

Das Trennen von schreibenden und lesenden Vorgängen setzt sich im Code fort, außerdem finden sich hier auch die fachlichen Bezeichnungen. Unterschieden wird zwischen Funktionen, die den Zustand der Anwendung verändern, und Funktionen, die den aktuellen Zustand auslesen und zurückgeben. Damit implementiert die Anwendung eine einfache Form des CQRS-Entwurfsmusters [1], das genau diese Trennung empfiehlt.

Ebenfalls implementiert ist das Validieren der Eingaben mit Hilfe von JSON-Schemata und eine einfache RAM-basierte Datenhaltung, die sich aber problemlos gegen einen datenbankbasierten Ansatz austauschen ließe. Einen Client gibt es bislang nicht, allerdings lässt sich die Kommunikation mit dem HTTP API zum manuellen Testen leicht über Werkzeuge wie curl umsetzen.

Das größte Manko im Code ist die derzeit fehlende Struktur. Zwar sind der HTTP-Server (./app.js), das API (./lib/getApp.js) und die Datenhaltung (./lib/Todos.js) grundsätzlich getrennt, aber insbesondere im API werd n zahlreiche Aspekte vermischt. Das besser zu strukturieren, ist Bestandteil dieses Artikels. Das zweite Problem besteht in der bislang lediglich manuellen Qualitätssicherung, die durch die Anwendung von Coderichtlinien und das Ausführen von automatisierten Tests deutlich beschleunigt und verbessert werden könnte.

Coderichtlinien anwenden

Das Anwenden von Coderichtlinien ist der einfachste Teil. Unter einer Coderichtlinie versteht man eine Vorgabe, die festlegt, wie Code zu formatieren oder welches Sprachmerkmal in einer bestimmten Situation zu verwenden ist. Ein einfaches Beispiel wäre die Festlegung, Code generell mit zwei Leerzeichen einzurücken und Vergleiche stets mit dem typsicheren ===-Operator durchzuführen. In beiden Fällen kann man selbstverständlich versuchen, das von Hand regelmäßig zu überprüfen. Diese Arbeit ist allerdings zeitaufwendig und fehleranfällig. Daher empfiehlt es sich, diese Aufgabe einem Werkzeug zu übertragen, das die Überprüfung automatisiert durchführen kann. Ein solches Werkzeug wird als Linter bezeichnet. Für JavaScript gibt es verschiedene Linter, wobei ESLint [2] den De-facto-Standard darstellt.

Grundsätzlich ist es ein Leichtes, ESLint zu einem Projekt hinzuzufügen [3]. Dafür muss nur das Modul eslint mit Hilfe von npm installiert werden. Da ESLint in dem Fall nicht für die Ausführung der Anwendung relevant ist, sondern nur zur Entwicklungszeit benötigt wird, kann man das Modul als sogenannte devDependency installieren, also als eine Abhängigkeit, die nur für die Entwicklung relevant ist. Dazu muss npm beim Aufruf der Parameter --save-dev übergeben werden:

$ npm install eslint --save-dev

Nun gilt es, ESLint aufzurufen. Das erfolgt über das in der Node.js-Installation enthaltene Werkzeug npx, mit dem ausführbare Module aufgerufen werden können. Allerdings ist der Aufruf von $ npx eslint ernüchternd, er bewirkt nämlich nichts. Der Grund ist, dass ESLint als Parameter eine Liste der Dateien erwartet, die überprüft werden sollen. Da man in der Regel nicht sämtliche Dateien in allen Unterverzeichnissen einzeln angeben möchte, kann man ein sogenanntes Glob-Pattern verwenden, das die gewünschten Dateien beschreibt. Wichtig ist, darauf zu achten, dass man Anführungszeichen um das Pattern setzt, da ansonsten nicht ESLint die Pfade auflöst, sondern die Shell:

$ npx eslint './**/*.js'

Leider bewirkt auch dieser Aufruf nicht das gewünschte Ergebnis, aber immerhin weist ESLint nun darauf hin, dass es keine Konfiguration finden kann. ESLint ist nämlich in sehr hohem Maße konfigurierbar, was bedeutet, dass man für jedes Projekt individuell festlegen kann, welche Coderichtlinien aktiv sein sollen. Eine solche Konfiguration lässt sich als Ausgangsbasis erzeugen, indem man ESLint mit dem Parameter --init aufruft, es gibt jedoch noch einen anderen Weg. Es ist nämlich gar nicht ratsam, in jedem Projekt eine eigene ESLint-Konfiguration abzulegen, da man in der Regel eine einheitliche Konfiguration für alle Projekte haben möchte – immerhin soll beispielsweise die Einrückung nicht in dem einen Projekt so und in dem anderen Projekt anders sein, sondern stets auf die gleiche Art erfolgen. Deshalb bietet ESLint die Möglichkeit, eine Konfiguration in ein eigenes npm-Modul auszulagern, das dann in einem Projekt installiert werden kann. Die Konfigurationsdatei im Projekt muss dann nur noch auf dieses npm-Modul verweisen. Solche Konfigurationen können sich in ihrer Komplexität unterscheiden. Eine besonders strikte Variante ist eslint-config-es [4], die leicht installiert werden kann:

$ npm install eslint-config-es --save-dev

Anschließend bedarf es nur noch einer Konfiguration...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang