Richtig klein: Hat Modularisierung versagt?

Seite 2: Immer kleiner

Inhaltsverzeichnis

Es braucht einen Ausweg aus dem Teufelskreis. Wenn der Auslöser für die Schwierigkeiten ist, dass das Modul zu groß war, wie wäre es mit kleineren Modulen? Und zwar so klein, dass das Team sie im Notfall nicht wartet, sondern komplett ersetzt!

Der Vorschlag klingt zunächst absurd. Praktisch jeder Softwareentwickler hat schon einmal katastrophale Erfahrung damit gemacht, ein Modul "mal kurz" zu ersetzen. Das klingt vorher immer einfach, führt aber bei der Umsetzung zu furchtbaren Fehlschlägen.

Ja, aber diesmal sind die Modulgrenzen so klein, wie es eben geht. Als Hausnummer: so klein, dass ein Einzelner die Anforderung in ein paar Tagen implementieren kann. Weil es sich um ein Modul handelt, gibt es klare, explizite Kontrakte in alle Richtungen, und es ist sichergestellt, dass sich die Gegenseiten daran halten. Außerdem existiert eine Dokumentation über die Kontrakte und darüber, was das Modul tun soll.

Daneben gibt es eine Testsuite mit hoffentlich hundertprozentiger Abdeckung des Problemraums, die sich nicht nur einfach wiederverwenden lässt, sondern die auch ein Gerüst darstellt, um eine Neuimplementation von Anfang an fehlerfrei zu halten.

An der Stelle sei eine wichtige Frage gestellt: Was ist wichtiger: Code oder Dokumentation?

Die Antwort lautet eindeutig: die Dokumentation. Das war vermutlich immer der Fall, aber im Kontext der Modularisierung wird offensichtlich, warum dem so ist. Der Hauptgrund für scheiternde Projekte ist, dass Programmiererinnen und Programmierer zu viele Freiheitsgrade hatten. Je klarer vorher formuliert wurde, was getan werden muss, desto weniger kann bei der Umsetzung schiefgehen.

Besser noch: Wer bei der Reimplementierung weiß, dass eine grundsätzlich funktionierende Variante existiert, weiß, dass die Aufgabe lösbar ist. Das kann Menschen mit Selbstzweifeln die Produktivität verdoppeln.

Die Idee der kleinen Module lässt sich als Hybrid aus Wasserfall und Agile sehen. Auf der einen Seite existieren beim Programmieren die klaren Vorgaben eines Pflichtenheftes wie beim Wasserfallmodell, aber wenn etwas nicht klappt, gibt es wie bei Agile immer noch die Option, die Modulstruktur zu überdenken.

Wahrscheinlich würden in einer Welt mit kleinen Modulen ähnliche psychologische und soziale Effekte wirken wie derzeit bei den großen Modulen. Wo nun eine Handvoll größerer Module auf der Liste des Wartungspersonals steht, wären es deutlich mehr kleinere Module. Es ist davon auszugehen, dass sie in der Summe das kognitive Limit der Einzelnen genauso sprengen wie weniger größere Module.

Allerdings ist das deutlich weniger schlimm, weil die Module von vornherein darauf ausgelegt sind, dass eine einzelne Person sie in ein paar Tagen ersetzen kann. Wenn sich niemand findet, der das Modul versteht oder einen Fehler diagnostizieren kann, ersetzt man einfach das zu komplexe Modul.

Ein wichtiger Kritikpunkt an dem Modell kleiner Module bleibt übrig: Es verringert die Komplexität nicht, sondern verschiebt sie lediglich. Gab es vorher ein paar große Bausteine, sind es nun viele kleine. Deren Verwaltung bringt ihre eigenen Herausforderungen mit sich.

An dieser Stelle sei an die leftpad-Apokalypse im Node-Universum erinnert, die durch kleine Module aufkam. Jemand hatte ein Modul namens leftpad geschrieben, das eine Zeichenkette nimmt und am Anfang Leer- oder andere Füllzeichen einfügt, bis sie eine bestimmte Länge hat. Es handelt sich um eine triviale Formatierungsfunktion, die unter anderem für die tabellarische Ausgabe von Daten erforderlich ist. Der Code war elf Zeilen lang.

Eines Tages hat der Entwickler leftpad aus Trotz gelöscht, weil npm ein anderes seiner Module nach einer Markenrechtsstreitigkeit rausgeschmissen hatte. Nachdem er leftpad gelöscht hatte, kollabierten einige wichtige Projekte wie Node.js und Babel, weil sie Dependencies zu leftpad hatten.

So abschreckend das Beispiel ist, hat es wenig mit der Modulgröße zu tun. Wenn ein Modul aus der Liste der Projektabhängigkeiten verschwindet, sind die Probleme unabhängig von der Größe. Tatsächlich ist es in dieser Situation deutlich besser, wenn ein leicht zu ersetzender Elfzeiler verschwindet als ein Framework mit Millionen von Codezeilen.

Organisationen werden sich größtenteils nicht auf das Risiko einlassen, dass Module plötzlich nicht mehr verfügbar sind, zu denen Abhängigkeiten bestehen. Intern können sie sicherstellen, dass keine Module verschwinden. Extern sollten sie nur die Module verwenden, deren Lizenz erlaubt, dass die Organisation ein Backup vorhält und weiterverwendet, wenn es extern nicht mehr verfügbar ist.

Wenn ein Projekt externe Module nutzt, steigt die Wahrscheinlichkeit eines Ausfalls mit sinkender Modulgröße und damit verbundener wachsender Zahl der Module. Auf der anderen Seite sinkt aber ebenso der Aufwand, um sich durch Neuschreiben des Moduls zu retten – in manchen Fällen wird eine Rettung dadurch überhaupt erst möglich.

Das leftpad-Problem zeigt aber ein anderes Detail auf, das tatsächlich vorausschauend gelöst werden muss: Es war nicht trivial zu ersetzen, weil im Node-Universum (wie in nahezu allen anderen Systemen) Module Namen haben, mit denen andere Projekte sie einbetten. Ein Name hat im Wertesystem aber Konnotationen wie Eigentum in Form von Markenrechten. Dass ein Autor sein Modul XY löscht, heißt nicht, dass der Name XY frei ist und jemand eine alternative Implementierung unter demselben Namen publizieren darf.

Ein Lösungsansatz wäre, ein Modul nicht mit dem Namen zu referenzieren, sondern beispielsweise mit dem Hash über die verwendeten Funktionsprototypen. Damit könnte der Paketmanager oder das Build-System automatisch eine passende Implementation heraussuchen.

Darüber ließe sich sogar ein Anreizsystem etablieren: Es kommt die Alternative mit der besten Testabdeckung zum Einsatz, und bei einem Gleichstand entscheiden die höheren Community-Bewertungen.