Im Artikel Der Rewrite-Reflex haben wir argumentiert, warum der Impuls neu zu schreiben meistens falsch ist. Akkumuliertes Wissen geht verloren. Die neuen Entwickler treffen dieselben alten Entscheidungen – diesmal ohne den Kontext der sie damals erklärt hätte. Ein Rewrite beginnt bei null. Sauber. Modern. Ohne dieses Wissen.
Im Artikel Refactoring – was kostet es, was kostet es nicht? haben wir gesagt: „Later braucht einen Termin." Technische Schulden akkumulieren stille Kosten. Wer nie neu bewertet, trifft keine Entscheidung – er lässt die Entscheidung treffen.
Heute kehren wir einen dieser Sätze um.
Es gibt Code bei dem later zu never wird – nicht durch Versäumnis, sondern durch Kalkül. Und es gibt Fälle wo never falsch ist. Wo ein Rewrite nicht der Reflex des Überforderten ist, sondern die präziseste Antwort auf eine präzise Frage.
Der Expression Manager von LimeSurvey ist so ein Fall.
Was der Expression Manager ist
Der Docblock am Anfang der Datei sagt es klarer als jede Analyse:
"The core of ExpressionScript Engine is a Recursive Descent Parser (RDP), based off of one build via JavaCC by TMSWhite in 1999."
Und dann der bemerkenswerteste Satz in der gesamten LimeSurvey-Codebasis:
"Functions that start with RDP_ should not be touched unless you really understand compiler design."
Das ist kein Kommentar. Das ist eine Warnung. Und sie steht dort seit mindestens 15 Jahren – git blame liefert den Beweis.
Der Expression Manager ist die Engine, die in LimeSurvey alles berechnet, was berechnet werden muss: Relevanzgleichungen, die entscheiden, ob eine Frage angezeigt wird, Validierungsregeln, die Eingaben prüfen, Piping, das Antworten in Texte einfügt, Navigation, die auf Basis von Bedingungen steuert. Jede Umfrage, die mehr tut als Fragen anzeigen, läuft durch ihn.
14.000 Zeilen Code. Die längste einzelne Methode – _CreateSubQLevelRelevanceAndValidationEqns() – hat 2145 Zeilen. Mehr als dreimal so viel wie createFieldMap(). Und der Kern des Systems ist 15 Jahre alt – entstanden zu einer Zeit, als PHP 5.3 noch neu war.
Warum niemand rangeht
Die Antwort ist nicht Feigheit. Sie ist Kalkül.
Ein RDP ist kein gewachsener Legacy-Code im klassischen Sinne. LimeMailer ist durch Feature-Einbau gewachsen – jede neue Anforderung hat sich irgendwo angehängt. createFieldMap() hat über die Jahre acht Verantwortlichkeiten angesammelt. Das ist organische Komplexität: sie entsteht durch Addition.
Der Expression Manager ist anders. Seine Komplexität ist intrinsisch. Ein Parser ist komplex, weil Sprachen komplex sind. Operator-Präzedenz, Klammern, verschachtelte Ausdrücke, Funktionsaufrufe mit variablen Argumenten, Strings mit Escape-Sequenzen – das sind keine Bugs im Design, das sind die Anforderungen.
Und dann ist da der ursprüngliche Autor: Thomas M. White, 1999, JavaCC. Der Code trägt das Wissen eines einzelnen Menschen, der tief in Compiler-Theorie war. Dieses Wissen ist nirgendwo anders dokumentiert. Es steckt in den RDP_-Methoden – und in dem Satz "unless you really understand compiler design."
Wer rangeht ohne dieses Verständnis, riskiert nicht einen Bug. Er riskiert, dass Umfragen, die seit Jahren korrekt laufen, plötzlich falsche Ergebnisse liefern. Still. Ohne Fehlermeldung.
Das ist der Grund, warum later hier zu never wurde. Nicht, weil die Entscheidung nie getroffen wurde, sondern weil das Risiko jeden potenziellen Gewinn übersteigt, solange man nicht versteht, was man anfasst.
Warum never hier trotzdem falsch ist
Genau an diesem Punkt kippt die Perspektive.
Der Expression Manager ist kein Geheimwissen. Er ist ein Recursive Descent Parser – eine der ältesten, am besten verstandenen Datenstrukturen der Informatik. Es gibt Lehrbücher darüber. Es gibt Implementierungen in jeder Sprache. Der Algorithmus ist formal beschreibbar.
Was TMSWhite 1999 in JavaCC gebaut hat, war für seine Zeit modern. JavaCC generierte Parser aus einer formalen Grammatik. Der Code, der dabei entstand, war maschinengeneriert, optimiert, korrekt – aber nicht lesbar. Nicht wartbar. Nicht veränderbar ohne JavaCC und die ursprüngliche Grammatikdatei.
15 Jahre LimeSurvey-Entwicklung haben darauf aufgebaut. Die Grammatikdatei existiert wahrscheinlich nicht mehr.
Das bedeutet: der aktuelle Code ist die Grammatik. Die 14.000 Zeilen sind die einzige lebende Dokumentation dessen, was der Expression Manager versteht und berechnet. Das ist das eigentliche Problem – nicht die Komplexität, sondern die fehlende Spezifikation.
Und gleichzeitig ist das die Lösung.
Der Rewrite der kein Reflex ist
Der klassische Rewrite-Fehler: man wirft den alten Code weg, schreibt neu, und verliert dabei das akkumulierte Wissen – die Edge Cases, die Bugfixes, die Sonderfälle, die irgendwann jemand gemeldet hat.
Beim Expression Manager funktioniert das anders. Das akkumulierte Wissen steckt nicht in der Implementierung. Es steckt in den Testfällen. Jede Umfrage, die korrekt funktioniert, ist implizit ein Testfall. Jeder Bug, der jemals gefixt wurde, hat einen konkreten Ausdruck, der vorher falsch berechnet wurde und danach richtig.
Das ist die Spezifikation des neuen Systems. Nicht geschrieben, aber vorhanden.
Ein Rewrite mit dieser Grundlage ist kein Sprung ins Dunkle. Es ist eine Übersetzung: den bestehenden Code als Orakel benutzen, die implizite Grammatik rekonstruieren, eine explizite Grammatik schreiben, einen neuen Parser bauen, der dieselben Ergebnisse liefert – und dann, Schritt für Schritt, mit den alten Testfällen verifizieren.
Der Unterschied zum Rewrite-Reflex ist präzise: man schreibt nicht neu, weil der alte Code hässlich ist. Man schreibt neu, weil die Grundlage – ein RDP – formal spezifizierbar ist und die neue Implementierung beweisbar korrekt sein kann.
Was KI hier leisten kann – und was nicht
2026 ist ein anderes Jahr als 1999. Nicht wegen der Hardware, sondern wegen der Werkzeuge.
Ein Recursive Descent Parser für eine wohlverstandene Ausdruckssprache ist ein Problem, das KI heute substanziell unterstützen kann. Die Grammatik aus dem bestehenden Code rekonstruieren – RDP_-Methoden lesen, Produktionsregeln ableiten, in EBNF übersetzen. Einen neuen Parser aus einer expliziten Grammatik generieren. Testfälle aus dem bestehenden Verhalten ableiten.
Was KI nicht kann: die Domäne verstehen. LimeSurvey-spezifische Funktionen, Token-Kontexte, Relevanzlogik – das ist Wissen, das ein Entwickler mitbringen muss, der LimeSurvey kennt. Jemand, der sieben Jahre mit der Plattform gearbeitet hat und weiß, warum eine Bedingung auf {TOKEN:ATTRIBUTE_1} zugreifen können muss.
KI und Domänenwissen zusammen – das ist die Kombination, die diesen Rewrite möglich macht. Keine von beiden allein. Und das ist der entscheidende historische Punkt: vor fünf Jahren war diese Kombination nicht verfügbar. Der Rewrite war nicht nur riskant – er war schlicht nicht praktisch durchführbar. Heute ist er es. Nicht trivial. Aber erstmals realistisch.
Was das für die Serie bedeutet
Wir haben in dieser Serie viel über Geduld gesprochen. Über schrittweise Migration, über Composer Packages, über den Wert des akkumulierten Wissens. Über den Rewrite-Reflex als Fehler.
Der Expression Manager ist die ehrliche Ausnahme, die diese Regel schärfer macht.
Nicht jeder komplexe Code sollte bewahrt werden. Manchmal ist die Komplexität nicht das Wissen – sie ist die Schale, die das Wissen verbirgt. Und wenn die Schale so hart geworden ist, dass niemand mehr rangeht, wenn later zu never geworden ist, ohne dass je jemand diese Entscheidung bewusst getroffen hat, dann ist der Rewrite nicht der Reflex des Überforderten.
Dann wird er zur eigentlichen Arbeit.
"Functions that start with RDP_ should not be touched unless you really understand compiler design."
Vielleicht besteht die richtige Antwort auf diesen Satz nicht nur aus Respekt. Vielleicht ist die Antwort: dann lernen wir Compiler Design.