/ Software-Entwicklung / the next big thing: Wie sich Node.js-Module auf Verzeichnis- und Dateiebene strukturieren lassen

the next big thing: Wie sich Node.js-Module auf Verzeichnis- und Dateiebene strukturieren lassen

Gerfried Steube on November 24, 2016 - 6:25 am in Software-Entwicklung

Eine häufig gestellte Frage im Kontext von Node.js lautet, wie man Module auf Verzeichnis- und Dateiebene strukturiert. Was fehlt, ist ein gemeinsamer und verbindlicher Standard. Ein Vorschlag.

Viele meiner Kunden fragen, wie man Module für Node.js auf Verzeichnis- und Dateiebene strukturiert. Die Frage ist verständlich, schließlich verfügen die meisten über Erfahrung in anderen Technologien, wo eine gewisse Struktur bereits von Haus aus vorgegeben wird.

Sucht man im JavaScript- und Node.js-Umfeld nach verbindlichen Standards, wird man enttäuscht. Zwar gibt es Ansätze, beispielsweise den Codestil zu vereinheitlichen, doch selbst daran scheiden sich bereits die Geister: JavaScript gänzlich ohne Semikolons zu schreiben finden verhältnismäßig viele Entwickler befremdlich.

Dementsprechend lang ist die Liste an Konfigurationen und Erweiterungen allein für ESLint. Wichtig ist hierbei aber letztlich gar nicht so sehr, dass alle Entwickler einen einzigen Standard verwenden, sondern dass zumindest jedes Team beziehungsweise jedes Unternehmen einen internen Weg festlegt. Nichts ist lästiger als fehlende Coderichtlinien innerhalb eines Teams.

Module strukturieren

Doch wie steht es um die Verzeichnis- und Dateistruktur von Modulen? Im Gegensatz zu Vorgaben für Coderichtlinien ist mir hier kein einziges Projekt bekannt, das sich diesem Thema widmet. Das könnte man theoretisch als Zeichen dafür deuten, dass die Frage nicht von Belang ist, doch die Praxis lehrt das Gegenteil.

Wir, das heißt meine Kollegen bei the native web und ich, entwickeln seit rund vier Jahren tagtäglich mit JavaScript und Node.js. Daher hat sich für uns ein Vorgehen herausgebildet, wie wir Module strukturieren.

Fraglos ist das weit davon entfernt, vollständig oder perfekt zu sein, doch für uns erfüllt es seinen Zweck – und das Feedback von unseren Kunden bekräftigt uns in der Annahme, dass es zumindest eine gute Ausgangsbasis darstellt, die in der Regel ohne Anpassungen übernommen werden kann.

Die oberste Ebene organisieren

Zunächst gibt es in jedem Modul zwei Dateien, die zwingend auf der obersten Ebene liegen müssen: Das ist zum einen die Datei package.json, zum anderen die Datei .gitignore. Da wir sämtliche unserer Module stets mit einer Dokumentation in Form einer Markdown-Datei ausstatten, ist die dritte Datei auf der obersten Ebene die README.md.

Ergänzend gibt es zwei Verzeichnisse, lib und test, die den eigentlichen Code des Moduls beziehungsweise die Unit- und Integrationstests enthalten.

Als Build-Werkzeug verwenden wir roboter, einen selbstentwickelten Convenience-Layer für gulp, der standardisierte Aufgaben für alle Module zur Verfügung stellt und sich auch darum kümmert, dass in jedem Modul die gleichen Coderichtlinien zur Verfügung stehen, ohne diese redundant pflegen zu müssen.

Dafür benötigt man die Datei roboter.js, außerdem ist eine rudimentäre Konfigurationsdatei für ESLint erforderlich, um das Überprüfen der Coderichtlinien in Echtzeit in Atom zu aktivieren. Daher braucht man zusätzlich auch noch die Datei .eslintrc.json. Beide Dateien liegen ebenfalls im obersten Verzeichnis.

Schließlich wird noch die Datei circle.yml ergänzt, die die Konfiguration für unseren Build-Server enthält. Fasst man das alles zusammen, erhält man folgende Blaupause:

some-module/
lib/
test/
.eslintrc.json
.gitignore
circle.yml
package.json
README.md
roboter.js

Alle anderen Verzeichnisse und Dateien, die beispielsweise von Werkzeugen, Editoren oder IDEs angelegt werden, schließen wir über Einträge in der Datei .gitignore von der Versionsverwaltung aus. Ansonsten würden sich nämlich im Lauf der Zeit diverse Verzeichnisse und Dateien ansammeln, die von der Umgebung einzelner Entwickler und nicht vom Modul selbst abhängen.

Den Code strukturieren

Die Struktur des lib-Verzeichnisses ist rasch erklärt. Die Hauptdatei des Moduls, die in der Datei package.json unter dem Eintrag main hinterlegt ist, erhält stets den gleichen Namen wie das Modul selbst.

Die Namen von Modulen werden immer vollständig in Kleinbuchstaben geschrieben, als einziges Sonderzeichen ist der Bindestrich zulässig. Ist ein solcher enthalten, wird im Dateinamen entsprechend Camelcase verwendet. Aus dem Modulnamen get-routes wird daher der Dateiname lib/getRoutes.js.

Alle übrigen Dateien und Verzeichnisse innerhalb von lib ergeben sich aus der Struktur des Codes und folgen keiner gesonderten Ordnung. Allerdings gilt die Regel, dass eine Datei stets so heißt wie der Name des Elements, das sie exportiert. Das bedeutet, dass alle Dateinamen im Regelfall mit einem Kleinbuchstaben beginnen, es sei denn, sie enthalten eine Konstrukturfunktion.

Auf die Art lässt sich bereits am require ablesen, wie das importierte Element zu nennen ist und ob es sich beispielsweise um eine Konstruktorfunktion handelt. Das verringert den Bedarf, stets noch einmal in die einzelnen Dateien hineinschauen zu müssen.

Die Tests strukturieren

Das test-Verzeichnis enthält zunächst zwei weitere Verzeichnisse, units und integration. Das hängt damit zusammen, dass roboter zwischen Unit- und Integrationstests unterscheidet und beide gesondert voneinander ausführen kann. Das lässt sich prinzipiell auch anders konfigurieren, im Normalfall belassen wir es aber bei dieser Vorgabe.

Das Verzeichnis test/units spiegelt die Verzeichnisstruktur aus lib. Das bedeutet, dass wenn es zum Beispiel eine Datei namens lib/foo/bar.js gibt, dass es dann ein entsprechendes Pendant namens test/units/foo/barTests.js gibt. Das erleichtert das Auffinden der zu einem Stück Code gehörenden Tests.

Wie man außerdem sieht, erhalten die Dateien, die Tests enthalten, das Suffix Tests. Dafür gibt es zwar keinen technischen Grund, es erleichtert aber das Lesen von Stacktraces: Bereits am Dateinamen lässt sich auf dem Weg ablesen, ob ein Fehler aus den Tests oder dem zu testenden Code stammt.

Sonstige Dateien

Gelegentlich gibt es noch weitere Dateien, die zu einem Projekt gehören, die allerdings keinen Code enthalten. Dazu zählen beispielsweise zusätzliche PDF-Dateien, die Algorithmen näher erläutern, oder Bilder, die in der Dokumentation verwendet werden. Dafür legen wir auf der obersten Ebene gegebenenfalls die Verzeichnisse doc und images an.

Beispielprogramme, die die Verwendung des Moduls demonstrieren, werden in samples abgelegt, Zertifikate in keys. Auch diese beiden Verzeichnisse sind optional und befinden sich, sofern sie existieren, direkt auf der oberen Ebene.

Fazit

Damit ergibt sich in der Maximalausstattung folgende Struktur, wobei einige Verzeichnisse wie beschrieben optional sind:

some-module/
doc/
images/
keys/
lib/
someModule.js
samples/
test/
integration/
units/
someModuleTests.js
.eslintrc.json
.gitignore
circle.yml
package.json
README.md
roboter.js

tl;dr: Für JavaScript und Node.js gibt es keinen einheitlichen Standard, wie Module zu strukturieren sind. Als Vorschlag für eine Vorlage kann die bei the native web eingesetzte Struktur dienen.

Read more on: Source

Comments are disabled