Im Artikel über createFieldMap() haben wir gesehen was eine GodFunction ist, wie sie entsteht, und wie ein Weg heraus aussehen könnte: ein sauberes Composer Package, vollständige QA-Kette, 100% Testbarkeit.
Der Plan ist klar. Die Frage die danach kommt, ist schwieriger:
Was kostet das? Und was kostet es, es nicht zu tun?
Das ist keine technische Frage mehr. Das ist eine unternehmerische. Und sie landet früher oder später auf dem Tisch des CTOs oder Lead Developers – meistens dann wenn das Budget knapp ist und die Roadmap voll.
Das Grundproblem: asymmetrische Sichtbarkeit
Technische Schulden haben eine unangenehme Eigenschaft: ihre Kosten sind asymmetrisch sichtbar.
Die Kosten des Refactorings erscheinen sofort, konkret und als Einzelposten – Entwicklerwochen, blockierte Features, Testaufwand, Budget. Sie sind greifbar, planbar, und lassen sich in ein Spreadsheet eintragen.
Die Kosten des Nicht-Refactorings dagegen verteilen sich unsichtbar über Monate und Jahre. Jede neue Anforderung dauert 20% länger als sie müsste. Ein neuer Entwickler braucht drei Monate statt drei Wochen um produktiv zu werden. Ein Bug taucht alle sechs Monate auf und kostet jedes Mal zwei Tage Debugging. Ein erfahrener Entwickler verlässt das Team aus Frustration – und niemand zieht den direkten Zusammenhang zu einer 600-Zeilen-Funktion ohne Tests.
Niemand stellt für diese Kosten eine Rechnung aus. Sie erscheinen nicht im Sprint-Board, nicht im Budget-Meeting, nicht im Jahresbericht. Sie sind real – aber unsichtbar.
Das ist der Grund warum ein „refactor later"-Kommentar 13 Jahre stehen bleiben kann. Nicht weil niemand es wollte. Sondern weil die Kosten des Wartens nie sichtbar gemacht wurden.
Zwei Szenarien, ein Beispiel
Nehmen wir createFieldMap() als konkretes Beispiel – eine Funktion mit 600+ Zeilen, acht Verantwortlichkeiten, einem nachgewiesenen SQL-Bug im Question-Preview-Pfad, und einem „refactor later"-Kommentar der seit 2012 unverändert im Code steht.
Wer nicht refactort, kauft sich kurzfristig Ruhe. Keine Unterbrechung, keine blockierten Features, kein Budget-Aufwand. Aber der Preis zeigt sich mittelfristig: jede Anforderung die createFieldMap() berührt dauert länger, das Onboarding neuer Entwickler erstreckt sich auf drei bis vier Monate, und der SQL-Bug wartet still auf seinen Moment – den falschen Moment, bei einem Kunden, unter Zeitdruck. Langfristig wächst die Funktion weiter, weil sie der einfachste Ort für den nächsten Feature-Einbau bleibt. Das Composer Package das die Logik kapseln könnte, existiert nicht.
Kein Unit Test kann die Funktion isoliert aufrufen. Die technische Schuld beginnt messbare Folgekosten zu erzeugen.
Wer refactort, investiert zwei bis drei Entwicklerwochen und blockiert in dieser Zeit Features. Das Risiko sind Regressionen die durch Tests abgefangen werden müssen – ein echtes Risiko, kein imaginäres. Aber mittelfristig sind neue Anforderungen isoliert umsetzbar, das Package ist dokumentiert und verständlich, PHPStan läuft auf Level 8 oder höher, und Bugs werden vor dem Release gefunden statt danach. Langfristig entwickelt sich das Package unabhängig, neue Fragetypen werden als Strategy-Klassen implementiert ohne die Funktion aufzublähen, und die vollständige QA-Kette läuft automatisiert.
Die Kosten in Zahlen
Eine grobe Schätzung – nicht exakt, aber für ein Budget-Gespräch überzeugend genug.
Das Refactoring kostet einmalig etwa 20.000 bis 25.000 Euro: zwei bis drei Entwicklerwochen für das Composer Package, dazu Testaufwand und Review. Das Nicht-Refactoring kostet laufend: etwa 8.000 Euro pro Jahr durch längere Entwicklungszeiten bei createFieldMap()-Änderungen, etwa 6.000 Euro durch verlängertes Onboarding neuer Entwickler, etwa 3.200 Euro durch wiederkehrendes Bug-Debugging. Das ergibt rund 17.000 Euro pro Jahr – Tendenz steigend, weil die Funktion wächst und die Kopplung zunimmt.
Das Refactoring amortisiert sich in unter 18 Monaten. Ab dann ist jedes Jahr ohne Refactoring teurer als das Refactoring selbst gewesen wäre.
Die tatsächlichen Zahlen hängen von Teamgröße, Stundensatz und Projektumfang ab. Aber die Größenordnung ist real – und sie reicht für ein ehrliches Gespräch.
Wann ist der Moment?
Es gibt drei Signale die eindeutig sind.
Das erste: die nächste Anforderung ist nicht umsetzbar ohne Zittern. Wenn ein Entwickler eine neue Anforderung bekommt und der erste Gedanke ist „ich hoffe ich breche damit nichts" – dann ist der Moment da. Nicht vorher, nicht nach einem festen Zeitplan. Genau dann.
Das zweite: der Onboarding-Aufwand übersteigt einen Sprint. Wenn ein neuer Entwickler länger als zwei Wochen braucht um eine Änderung an einem bestimmten Modul produktiv umzusetzen, ist die Cognitive Load zu hoch. Das ist kein Kompetenzproblem – das ist ein Strukturproblem.
Das dritte: derselbe Bug taucht zum dritten Mal auf. The Rule of Three: beim ersten Mal löst man es pragmatisch, beim zweiten Mal bemerkt man das Muster, beim dritten Mal refactort man. Wer beim dritten Mal noch wartet, zahlt exponentiell.
Das Gespräch mit der Geschäftsführung
Das schwierigste an technischen Schulden ist nicht die Technik. Es ist die Kommunikation.
Entwickler sprechen von „schlechtem Code", „Kopplung", „fehlenden Tests". Das ist die falsche Sprache für ein Budget-Gespräch. Die richtige Sprache ist die Sprache der Kosten und Konsequenzen: „Jede neue Funktion in diesem Bereich kostet uns 20% mehr Zeit als sie müsste." Oder: „Wir haben einen Bug der seit 13 Jahren im Code sitzt und beim nächsten falschen Aufruf einen Produktionsfehler verursacht." Oder: „Ein neuer Entwickler braucht drei Monate statt drei Wochen – das kostet uns pro Einstellung X Euro extra."
Das ist keine Vereinfachung. Das ist Übersetzung. Technische Realität in unternehmerische Sprache – und genau das ist die Aufgabe eines Lead Developers oder CTOs der dieses Gespräch führen muss.
Was createFieldMap() uns lehrt
Der „refactor later"-Kommentar aus dem Jahr 2012 ist kein Versagen. Er dokumentiert vielmehr eine nachvollziehbare Entscheidung unter Zeitdruck: Das Problem war bekannt, aber in diesem Moment nicht das dringendste.
So entstehen die meisten technischen Schulden — nicht durch Ignoranz, sondern durch Priorisierung.
Das eigentliche Problem liegt deshalb nicht im Aufschieben selbst. Softwareentwicklung besteht zwangsläufig aus Kompromissen. Kritisch wird es erst dann, wenn aus einem temporären Aufschub ein dauerhafter Zustand wird, ohne dass die Entscheidung jemals bewusst erneut betrachtet wird.
„Later" ist kein Fehler. „Later ohne Neubewertung" ist einer.
Für createFieldMap() existiert heute ein konkreter Plan: ein eigenständiges Composer Package, eine vollständige QA-Kette und eine schrittweise Migration, die Risiken kontrollierbar macht. Die Kosten sind abschätzbar, die Auswirkungen nachvollziehbar.
Damit ist die Situation keine technische Unbekannte mehr, sondern eine klassische Investitionsentscheidung unter begrenzten Ressourcen.
Und wie bei jeder Investition stellt sich letztlich nicht die Frage, ob Kosten entstehen — sondern nur, wann und unter welchen Bedingungen man sie tragen möchte.
„Later" braucht deshalb kein Versprechen, sondern einen Termin.