Theorie, die bereits existierte
Jeder MOAD-Defekt hatte Jahrzehnte vor der systematischen Erkennung 2026 eine bekannte Lösung. Die Defekte blieben nicht bestehen, weil niemand Besseres wusste. Sie blieben bestehen, weil Wissen nicht dasselbe ist wie Erkennen.
MOAD-0001: O(N²) list.contains
Donald Knuth, 1973. The Art of Computer Programming, Volume 3: Sorting and Searching. Hash-Tabellen für O(1)-Lookup wurden 1973 vollständig mit Analyse spezifiziert. Der Unterschied zwischen O(N)-linearer Suche und O(1)-Hash-Lookup — dokumentiert, formalisiert, weit zitiert. Java lieferte HashSet in 1.0 (1996) aus. Python führte set als First-Class-Typ in 2.4 (2004) ein. Die Lösung existierte 30 Jahre, bevor sie zu einem Standard-Idiom in jedem Ökosystem wurde.
Richard Hamming, 1986. Bell Labs-Vorlesungen (später veröffentlicht als The Art of Doing Science and Engineering, 1997). Hamming lehrte explizit algorithmische Komplexität, den Unterschied zwischen korrekt und effizient sowie die Gefahr, Systeme zu bauen, die in kleinem Maßstab funktionieren, aber in großem Maßstab versagen. Er nannte es „Design für das Problem, das man heute sieht, nicht für das Problem, dem man morgen gegenüberstehen wird.“
MOAD-0002: Gekoppelter globaler gemeinsamer Zustand
David Parnas, 1972. „On the Criteria To Be Used in Decomposing Systems into Modules.“ CACM, Dezember 1972. Parnas argumentierte, dass Module durch Information Hiding zerlegt werden sollten – jedes Modul besitzt seinen eigenen Zustand, keine gemeinsamen veränderbaren Globals. Dies ist der direkte theoretische Vorgänger des Intertangle-Fixes. Parnas war eindeutig: globaler gemeinsamer Zustand erzeugt unsichtbare Kopplung, die Tests nicht aufdecken.
MOAD-0003: ThreadLocal-Identitätsleck
Java 1.2, 1998. ThreadLocal wurde als Standardbibliotheksklasse in Java ausgeliefert. In dem Moment, als Thread-Pooling und ThreadLocal zusammen existierten, war der Mechanismus für das Leck vorhanden. Der Defekt ist strukturell: ein Träger, dessen Lebensdauer der Thread und nicht die Arbeitseinheit ist. Die Dokumentation warnte bereits früh im Java-EE-Lebenszyklus davor.
MOAD-0004: Protokollierte Anmeldedaten
RFC 1945, 1996. HTTP/1.0 definierte den Authorization-Header. Der Defekt der Anmeldedaten-Protokollierung wurde möglich, als der Authorization-Header existierte. OWASP wurde 2001 gegründet und dokumentierte Anmeldedaten-Protokollierung als Schwachstellenklasse in seinen ersten Leitfäden. Das Muster: Authorization-Header → Log-Middleware → Klartext-Anmeldedaten auf der Festplatte. Bekannt seit der ersten HTTP-Auth-Spezifikation.
MOAD-0005: Thundering Herd / Cache Stampede
Unix-Kernel, 1993. Das „Thundering-Herd-Problem“ – N Prozesse, die gleichzeitig auf ein gemeinsames Ereignis geweckt werden – tauchte in Unix-Kernel-Entwicklungsdiskussionen bereits Anfang der 1990er-Jahre auf. Doug Schmidts Arbeiten zum Reactor-Pattern (1994) und Half-Sync/Half-Async (1995) adressierten die Synchronisation auf Infrastrukturebene. Die Cache-Stampede-Variante (N Threads berechnen denselben Wert bei einem Cache-Miss) wurde in der Literatur zu verteilten Systemen bis 2001 dokumentiert.
---
Theorie: vollständig. Detektionswerkzeuge: nicht vorhanden. Die Lücke zwischen „knowable“ und „detected“ beträgt je nach Defekt 28 bis 54 Jahre.
Die Knowability-Lücke
Die Zeitachse zeigt, dass jeder MOAD-Defekt mindestens 28 Jahre vor der systematischen Erkennung eine bekannte Lösung hatte. Die kürzeste Lücke (MOAD-0003) beträgt 28 Jahre. Die längste (MOAD-0002) beträgt 54 Jahre.
Dies ist keine Geschichte über Unwissenheit. Knuth, Parnas, Hamming – das sind die am häufigsten zitierten Autoren der Informatik. Ihre Arbeiten wurden an Universitäten verwendet. Ihr Vokabular (Big O, Information Hiding, algorithmische Komplexität) wurde zum Standardlehrstoff.
Warum Code verrottet: Fünf Bedingungen
Ein Defekt bleibt nicht zufällig bestehen. Fünf strukturelle Bedingungen, die gleichzeitig vorliegen, schaffen ein Verrottungsumfeld. Entferne eine davon, und Erkennung wird möglich.
Bedingung 1: Korrekte Ausgabe
Eine Liste und ein Set beantworten die Membership-Frage identisch. list.contains(x) und set.contains(x) liefern denselben booleschen Wert. Ein ThreadLocal, das eine veraltete Identität trägt, trägt immer noch eine Identität — sie gehört nur der falschen Anfrage. Protokollierte Anmeldedaten werden korrekt protokolliert — die Anmeldedaten erreichen die Log-Datei ohne Fehler. Der Defekt ist keine Fehlfunktion. Er ist nur in Bezug auf Kosten oder Sicherheitsfolgen eine Fehlfunktion. Tests, die die Ausgabe prüfen, bestehen. Tests, die Kosten oder Sicherheitsfolgen prüfen: größtenteils nicht geschrieben.
Bedingung 2: Keine Komplexitätstests in CI
Dijkstra sagte: „Tests zeigen die Anwesenheit von Defekten, nicht deren Abwesenheit.“ Hamming ergänzte: Die Defekte, für die wir testen, sind die Defekte, die wir finden. CI-Pipelines im Jahr 2026 testen: Korrektheit, Typsicherheit, API-Verträge, funktionales Verhalten. Sie testen nicht: algorithmische Komplexität pro Operation, Speicherwachstum pro Aufruf, Bereinigung von Authorization-Headern, Lebenszyklus von Thread-Identitäten.
Kein Test wird ausgeführt. Kein Test schlägt fehl. Die Pipeline ist grün. Der Defekt ist unsichtbar.
Bedingung 3: Small-N-Ursprung
Code wird in Entwicklungsumgebungen geschrieben und geprüft. Entwicklungsgraphen haben 50 Knoten. Entwicklungsanfragen haben 10 gleichzeitige Threads. Die Cache-Miss-Raten in der Entwicklung sind niedrig (warmer Cache, wenige Schlüssel). Bei N=50 beträgt die O(N²)-Kosten 2.500 Operationen. Unsichtbar. Bei N=50.000 betragen die Kosten 2.500.000.000 Operationen. Ein 17-Minuten-Build statt eines 1-Sekunden-Builds.
Der Autor, der den Code geschrieben hat, hat N=50.000 nie gesehen. Der Reviewer, der ihn genehmigt hat, hat N=50.000 nie gesehen. Der Defekt war beim Schreiben nicht sichtbar.
Bedingung 4: Copy wird ohne Kontext weitergegeben
Ein korrekter Algorithmus ist lehrreich. Tutorials lehren mit korrekten Beispielen. Dokumentation zeigt funktionierenden Code. Das gleiche Tarjan-SCC-Skelett — visited = [], inneres if n not in visited — erscheint in GHC, Maven, Python pip, Cargo, TypeScript-Compiler, Kotlin-Compiler, Scala-Compiler und javac. Verschiedene Teams, verschiedene Sprachen, verschiedene Jahrzehnte. Dasselbe Fossil. Die N=50 des ursprünglichen Autors verbreitet sich nicht mit dem Code. Was sich verbreitet: die korrekte Ausgabe. Was zurückbleibt: die Performance-Annahme.
Bedingung 5: Skalierung wächst um eingefrorenen Code
Code verschlechtert sich nicht. Infrastruktur skaliert. Ein Abhängigkeitsauflöser, der 2003 für 200 Pakete geschrieben wurde, läuft 2024 auf 50.000 Paketen. Niemand schreibt ihn neu — er funktioniert. Niemand profiliert ihn — die CI ist grün. Das N, das die O(N²)-Kosten katastrophal macht, kommt allmählich, unsichtbar, in Produktionsskalierung. Bis dahin ist der ursprüngliche Autor verschwunden. Der Code ist eine Abhängigkeit. Niemand berührt funktionierende Abhängigkeiten.
Diagnose: Fünf Bedingungen
Die fünf Bedingungen: korrekte Ausgabe, keine Komplexitätstests, Ursprung mit kleinem N, Kopie ohne Kontext, Skalierung wächst um eingefrorenen Code.
Alle fünf waren bei jedem MOAD gleichzeitig vorhanden. Das ist kein Zufall — es ist die strukturelle Signatur einer sedimentären Defektklasse.
Was Hamming sagte
Richard Hammings Vorlesungen von 1986 bei Bell Labs – 1997 als The Art of Doing Science and Engineering veröffentlicht – enthalten Warnungen, die wie direkte Beschreibungen des MOAD-Defektmusters klingen. Er beschrieb nicht MOAD. Er beschrieb die strukturelle Tendenz von Ingenieursystemen, sich um lokal korrekte Entscheidungen zu verhärten, die global teuer werden.
Hamming zur Komplexität: „Der Zweck des Rechnens ist Einsicht, nicht Zahlen. Aber man braucht die richtige Komplexität des Algorithmus, sonst kommen die Zahlen nie. Ein O(N²)-Algorithmus, der bei N=100 läuft, wird bei N=1.000.000 nicht mehr laufen, bevor man in Rente geht.“
Hamming zum Kopieren: „Große Ingenieure kopieren nicht einfach nur Lösungen. Sie verstehen, warum die Lösung funktioniert, unter welchen Bedingungen sie gilt und was sie brechen würde. Eine kopierte Lösung ohne ihre Bedingungen ist eine Zeitbombe.“
Hamming zum Testen: „Das zu testen, was man gemessen hat, ist nicht dasselbe wie das zu messen, was zählt. Wir bauen aufwendige Testsuiten für die Eigenschaften, die wir zu testen gewählt haben. Wir lassen die Eigenschaften ungetestet, die wir nicht gewählt haben. Was wir ungetestet lassen, ist das, was uns in der Produktion überrascht.“
Hamming im Maßstab: „Der Fehler, den du im ersten Jahr eines Projekts machst, ist der Fehler, den du noch im zehnten Jahr korrigierst. Frühe Annahmen verhärten sich. Das Projekt skaliert um sie herum. Niemand schreibt das Fundament neu.“
Die Lücke zwischen Warnung und Operationalisierung
Hammings Warnungen waren korrekt. Sie wurden gelehrt. Sie wurden zitiert. Sie wurden in Curricula vergeben. Aber eine Warnung ist kein Detektor. Hamming beschrieb die Form des Defekts. Er baute kein Tool, das in CI läuft und O(N²)-Hot-Pfade, ThreadLocal-Identitätslecks oder Credential-Logging markiert. Die Lücke zwischen „erkennbar“ und „detektierbar“ ist die Lücke zwischen einer Theorie und ihrer Operationalisierung als automatisierte Infrastruktur.
MOAD existiert, weil das Fachgebiet Korrektheitsinfrastruktur aufgebaut hat, aber keine gleichwertige Performance- oder Sicherheitsinfrastruktur. Unit-Tests: seit den 1970er Jahren Standard. Property-Based-Tests: seit den 1990er Jahren Standard. Algorithmische Komplexitäts-Benchmarks in CI: 2026 noch experimentell.
Operationalisierung der Warnung
Hamming warnte vor Komplexitätsverkalkung, ungetesteten Eigenschaften, kopierten Lösungen ohne ihre Bedingungen und Skalierung, die frühe Annahmen zerdrückt. Er gab uns den Wortschatz. Er gab uns nicht den Detektor.
Die MOAD-Pipeline schließt diese Lücke: scan → ticket → patch → unit test → disclose → PR → upstream merge. Das ist operationalisierter Hamming: nicht nur die Warnung, sondern automatisierte Erkennung und eine Fix-Pipeline.
Die Fester-Signatur
Ein Defekt der MOAD-Klasse hat eine erkennbare Signatur. Alle fünf Bedingungen liegen gleichzeitig vor. Alle fünf sind prüfbar, bevor auch nur ein Scan geschrieben wird:
1. Korrekte Ausgabe? Führe die Standard-Test-Suite aus. Wenn sie besteht, handelt es sich bei dem Defekt um eine Performance- oder Sicherheits-Eigenschaft, nicht um eine Korrektheits-Eigenschaft. Das bedeutet, dass das Standard-CI sie nicht erkennen wird.
2. Kein Komplexitätstest? Überprüfe die CI-Konfiguration. Gibt es eine Benchmark-Stufe? Vergleicht sie das algorithmische Verhalten (nicht nur die Laufzeit) mit einem früheren Commit? Wenn nicht: Bedingung erfüllt.
3. Small-N-Ursprung? Überprüfe den Git-Blame und den ursprünglichen Commit. Wie groß war der Datensatz in der ersten Implementierung? Ist diese Größe um mehr als das 100-fache kleiner als die aktuelle Produktionslast? Wenn ja: Bedingung erfüllt.
4. Kopie propagiert? Suche nach dem Muster im gesamten Codebase und in verschiedenen Ökosystemen. Erscheint dasselbe strukturelle Muster in N≥3 unabhängigen Codebases ohne gemeinsame Abstammung? Wenn ja: Das Fossil hat sich verbreitet. Jede Kopie: ein neuer Fester-Ort.
5. Skalierung wächst? Überprüfe die Produktionsmetriken. Wie groß ist N heute im Vergleich zu N beim ersten Deployment? Ist die Wachstumsrate anhaltend? Bei welchem N wird der Defekt betriebskritisch?
Wenn alle fünf Punkte geprüft und bestätigt sind: Du hast einen MOAD-Klassendefekt. Die Behebung ist immer eine einzeilige oder einmethodige Substitution. Die Entdeckung ist der schwierige Teil. Die Behebung ist der einfache Teil.
Das meinte Hamming: Engineering geht nicht um die Behebung. Die Behebung ist einfach, sobald man sie sieht. Engineering geht darum, Systeme zu bauen, die es ermöglichen, sie zu sehen.
Die Signatur anwenden
Die MOAD-Fester-Signatur: korrekte Ausgabe + kein Komplexitätstest + Small-N-Ursprung + Kopie propagiert + Skalierung wächst.
Diese Signatur ist nicht auf die fünf MOAD-Defekte beschränkt. Sie beschreibt eine Klasse von Defekten, die in jedem System fortbesteht, in dem Korrektheitstests das einzige automatisierte Qualitäts-Gate sind.