Konzepte statt Hypes

In der JavaScript-Szene erscheinen regelmäßig neue und aktualisierte Module. Das bringt das Ökosystem voran, kann allerdings zugleich schaden. Statt ständig den neuesten Trends hinterher zu jagen, empfiehlt sich ein Schulterblick in die Vergangenheit.

In Pocket speichern vorlesen Druckansicht 19 Kommentare lesen
Konzepte statt Hypes
Lesezeit: 14 Min.
Von
  • Golo Roden
Inhaltsverzeichnis

Die npm-Registry beherbergt derzeit über 400 000 Module. Während den meisten davon nicht allzu viel mediale Aufmerksamkeit zuteil wird, haben einige sehr viel Wirbel verursacht. Dazu zählen unter anderem Lodash, Immutable.js und React.

Die drei Module stehen exemplarisch für zahlreiche weitere, denen allen etwas gemein ist: Sie sind technisch und konzeptionell brillant, lösen bei vielen Entwicklern zunächst aber Unbehagen aus, da etwa die langfristige Relevanz unklar ist.

Einerseits ist das nicht verwunderlich. Das Tempo, in dem Entwickler neue Module veröffentlichen und alte aktualisieren, ist gerade in der JavaScript-Szene enorm hoch. Um nicht Gefahr zu laufen, abgehängt zu werden, bleibt gefühlt keine andere Option, als halbwegs zeitnah jedem Trend zu folgen. Andererseits ist es erschreckend, denn betrachtet man Lodash, Immutable.js oder React genauer, fällt auf, dass sie letztlich wenig Neues enthalten. Im Großen und Ganzen greifen sie lediglich auf diverse Konzepte funktionaler Programmierung zurück.

Dass Kenntnis Letzterer in Teilen der Entwicklerszene nicht genügend weit verbreitet ist, hängt sicherlich unter anderem mit der Blütezeit der objektorientierten Programmiersprachen gegen Ende des 20. und Beginn des 21. Jahrhunderts zusammen. Für lange Zeit waren die drei einflussreichsten Sprachen C++, Java und C#. Alle drei verfolgen das gleiche Paradigma und sind einander daher verhältnismäßig ähnlich.

Um neue Bibliotheken oder Frameworks besser einschätzen zu können, hilft folglich ein Blick in die Vergangenheit oder generell eine Auseinandersetzung mit grundlegenden Konzepten der Informatik, denn obwohl die genannten Tools gut darin sind, sie zu implementieren, können sie Entwicklern nicht die Entscheidung abnehmen, ob sich der Einsatz für ein spezielles Projekt lohnt.

Sollte an der Stelle die Frage aufkommen, warum gerade jetzt Konzepte funktionaler Programmierung wiederentdeckt werden, hilft ein kritischer Blick auf die Sprachen, die dem Paradigma der Objektorientierung folgen. Dabei fällt auf, dass sie viele der von ihr versprochenen Aspekte nicht einhalten konnte. Insbesondere die angekündigte Wiederverwendbarkeit hat nicht in dem Maß stattgefunden, wie es zunächst vorhergesagt wurde. Der englische Informatiker Joe Armstrong, der die Sprache Erlang entwickelt hat, beschrieb den Umstand folgendermaßen:

"The problem with object-oriented languages is they've got all this implicit
environment that they carry around with them. You wanted a banana but what you
got was a gorilla holding the banana and the entire jungle."

Hinzu kommt ein weiteres gravierendes Problem. Als Softwareentwickler konnte man sich früher darauf verlassen, dass die eigene Anwendung mit der nächsten Prozessorgeneration schneller ausgeführt werden würde. Software wurde quasi automatisch schneller. Heute gilt das nicht mehr, da die Taktfrequenz der Prozessoren, wenn überhaupt, nur noch unmerklich wächst. Stattdessen steigt heute die Zahl der verfügbaren Kerne, doch das nützt einer Anwendung erst einmal nichts. Um mehrere Kerne oder gar mehrere Prozessoren nutzen zu können, muss sich der Code einer Anwendung parallelisieren lassen.

Das ist in der Objektorientierung zum Teil schwer umzusetzen, da mehrere Threads den Zustand eines Objekts beeinflussen können, was spezielle Mechanismen zur Synchronisation erforderlich macht. Selbst wenn man äußerst akribisch vorgeht, führt das trotzdem rasch zu Konflikten wie Race-Conditions oder Deadlocks.

In der funktionalen Programmierung lassen sich diese Probleme einfach vermeiden, indem man schlichtweg ohne Zustand arbeitet. Funktionen verwenden stattdessen stets nur lokale Variablen. Dadurch, dass keine Rücksicht auf die Zustände anderer Programmteile zu nehmen ist, fällt die Parallelisierung mit ihr wesentlich leichter.

Doch das alleine genügt noch nicht. Außerdem ist nämlich darauf zu achten, die technischen und fachlichen Belange des Codes voneinander zu trennen. Möchten Entwickler beispielsweise eine Funktion schreiben, die eine Liste von Zahlen quadriert, lässt sich das auf den ersten Blick rasch mit dem folgenden Code bewerkstelligen:

const getSquares = function (numbers) {
const squares = [];

for (let i = 0; i < numbers.length; i++) {
squares.push(numbers[i] ** 2);
}

return squares;
};

Obwohl die einzelnen Schleifeniterationen vollständig unabhängig voneinander sind und die Schleife daher ein perfekter Kandidat für Parallelisierung wäre, ist das jedoch nicht ohne weiteres möglich. Das liegt daran, dass der Code explizit vorgibt, wie das Array zu durchlaufen ist. Den Umstand, dass die einzelnen Iterationen unabhängig voneinander sind, drückt er nicht aus und es ist für die Laufzeitumgebung äußerst schwierig zu erkennen.