Sie haben ein PHP-System übernommen, das seit Jahren im Produktivbetrieb läuft. Es verdient Geld, die Fachabteilung arbeitet täglich damit, und niemand kann Ihnen sagen, wie es funktioniert. Der ursprüngliche Entwickler ist weg, es gibt kein Wiki, keine Architekturskizze, keine README. Genau das ist der Normalfall in meiner Arbeit, und der erste Reflex ist meist der falsche.
Der falsche Reflex lautet: neu bauen. Ein System, das seit Jahren stabil läuft, ist aber kein Müll. Es ist der Beweis, dass die Fachlogik funktioniert. Diese Logik steckt oft nicht in einer sauberen Spezifikation, sondern in tausend kleinen Bugfixes, die über Jahre eingearbeitet wurden. Bei einer Neuentwicklung fangen Sie bei diesen Sonderfällen wieder bei null an. Das ist fast immer die teuerste und riskanteste Option.
Warum ein Legacy ohne Dokumentation kein Grund zur Panik ist
Das eigentliche Problem ist selten die Fachlogik. Das Problem ist der Code drumherum: verflochtene Abhängigkeiten, globale Zustände, direkter Datenbankzugriff mitten im Template, veraltete Bibliotheken. Die Geschäftsregeln selbst sind meistens gesund. Sie sind nur schwer zu erkennen, weil sie unter technischen Schulden begraben liegen.
Das ändert Ihre Aufgabe grundlegend. Sie müssen kein Wissen erfinden, sondern vorhandenes Wissen freilegen. Der Code ist die Dokumentation, auch wenn er unangenehm zu lesen ist. Und im Gegensatz zu einem Wiki lügt der Code nicht: Was im Produktivsystem läuft, ist die Wahrheit, nach der sich alle richten.
Wie fange ich bei einem Legacy ohne Dokumentation systematisch an?
Beginnen Sie nie mit dem Lesen von Code. Beginnen Sie mit dem Beobachten des laufenden Systems. Verschaffen Sie sich zuerst einen Überblick über die Ränder der Anwendung, bevor Sie ins Innere gehen. Ein bewährter erster Durchgang sieht so aus:
- Zugänge und Betrieb klären. Wo läuft das System, welche PHP-Version, welcher Webserver, wie kommt Code auf den Server? Gibt es Deployment oder wird per FTP hochgeladen? Das entscheidet, wie gefährlich jede Änderung ist.
- Die Datenbank zuerst verstehen. Das Schema verrät die Fachlichkeit oft klarer als der Code. Tabellennamen, Fremdschlüssel und Spalten zeigen Ihnen die Domäne. Exportieren Sie das Schema und lesen Sie es wie ein Inhaltsverzeichnis.
- Einstiegspunkte finden. Suchen Sie die Front-Controller, Routing-Dateien oder das alte
index.php. Von hier aus verzweigt sich alles. Bei Symfony oder Laravel finden Sie die Routen zentral, bei gewachsenen Eigenbauten oft verstreut. - Externe Abhängigkeiten kartieren. Welche APIs, Cronjobs, Zahlungsdienstleister, Mailserver hängen dran? Diese Integrationen sind die riskantesten Stellen bei jeder Änderung.
Charakterisierungstests statt Wunschdenken
Bevor Sie irgendetwas anfassen, sichern Sie das aktuelle Verhalten ab. Bei Legacy-Code schreiben Sie keine Tests gegen die Spezifikation, weil es keine gibt. Sie schreiben Charakterisierungstests (characterization tests): Tests, die festhalten, was das System heute tut, nicht was es tun sollte.
Konkret: Sie rufen einen Endpunkt mit realen Eingaben auf, nehmen die Ausgabe entgegen und frieren sie als erwartetes Ergebnis ein. Auch wenn die Ausgabe merkwürdig aussieht. Diese Tests sind Ihr Sicherheitsnetz. Sie sagen Ihnen sofort, wenn eine Umstrukturierung das Verhalten verändert. Ohne dieses Netz arbeiten Sie blind.
Welche Werkzeuge helfen beim Verstehen von altem PHP-Code?
Sie müssen den Code nicht allein im Kopf durchdringen. Statische und dynamische Analyse nehmen Ihnen die stumpfe Arbeit ab:
- Statische Analyse (PHPStan, Psalm). Auf niedriger Stufe gestartet, findet sie undefinierte Variablen, tote Codepfade und Typfehler. Das legt die brüchigsten Stellen offen, noch bevor Sie sie lesen.
- Abhängigkeits- und Aufrufgraphen. Werkzeuge, die visualisieren, welche Klasse welche aufruft, zeigen Ihnen die eng verknoteten Kerne und die losen Randbereiche. Ändern Sie zuerst die Ränder.
- Laufzeit-Profiling (Xdebug, Blackfire). Ein Trace eines echten Requests zeigt Ihnen den tatsächlich durchlaufenen Pfad. Das ist oft aussagekräftiger als jede statische Analyse, weil es toten Code sofort von lebendem trennt.
- Versionshistorie. Falls ein Git-Log existiert, ist es Gold wert. Häufig geänderte Dateien sind meist die Problemzonen und zugleich die fachlich wichtigsten.
Sicherheit gehört in diese erste Phase
Alte PHP-Systeme haben typische Schwachstellen: SQL-Injection durch direkt zusammengesetzte Queries, fehlende Ausgabe-Kodierung, veraltete Passwort-Hashes wie MD5, hartcodierte Zugangsdaten im Repository. Prüfen Sie das früh, aber ändern Sie es kontrolliert. Eine überstürzte Security-Korrektur ohne Testnetz kann das System schneller lahmlegen als jede Lücke. Notieren Sie die Funde, priorisieren Sie nach realem Risiko und schließen Sie die kritischsten zuerst, sobald Ihre Charakterisierungstests stehen.
Wie modernisiere ich, ohne alles neu zu schreiben?
Der Weg heißt schrittweise Verbesserung, nicht Big-Bang-Rewrite. Ein bewährtes Muster ist der sogenannte Strangler Fig: Sie legen eine neue Struktur um das alte System und ersetzen Funktion für Funktion, während der Rest weiterläuft. Bei PHP heißt das oft, ein modernes Framework wie Symfony oder Laravel schrittweise davorzusetzen und einzelne Routen nach und nach umzuleiten.
Fangen Sie mit dem an, was hohen Nutzen und geringes Risiko verbindet: Composer und Autoloading einführen, statt Dateien manuell zu inkludieren. Eine Datenbank-Abstraktion vor die rohen Queries setzen. Konfiguration aus dem Code in Umgebungsvariablen ziehen. Jeder dieser Schritte ist für sich testbar und deploybar. Sie bauen Vertrauen auf, statt es zu riskieren.
Ein ehrlicher Praxis-Tipp zum Schluss: Widerstehen Sie dem Drang, den Code beim ersten Lesen zu verurteilen. Was aussieht wie Chaos, ist oft eine sinnvolle Reaktion auf eine Anforderung, die Sie noch nicht kennen. Fragen Sie im Zweifel die Fachabteilung, warum ein Sonderfall existiert, bevor Sie ihn entfernen. Genau bei dieser Art von Übernahme, dem systematischen Einstieg in ein Legacy ohne Dokumentation, unterstütze ich mit LegacyWerk, wenn Sie einen zweiten Blick brauchen.