Was ist Legacy-Code-Archäologie?
Ein weiterer Artikel über Legacy-Code? Das ist eine gute Frage. Es wurde schon viel und oft über Legacy-Code geschrieben und doch möchte ich einen weiteren Artikel - vielleicht sogar mehrere - hinzufügen. Einfach, weil ich auch etwas zurückgeben möchte - dadurch, dass vielleicht du als Entwickler:in davon lernen kannst. Und auch, weil ich ganz spezifisch über PHP-Legacy-Code und dessen Eigenheiten sprechen möchte. Eben, weil ich ein PHP-Backend-Entwickler bin.
Mein Name ist Marcus, ich entwickle seit 1999 (also seit PHP 3) Webseiten und Webapps mit PHP. Ich kann durchaus von mir behaupten, schon eine Menge an Legacy-Code produziert zu haben, bestimmt auch ganz fürchterlichen. Und ich hoffe, niemand musste sich damit herumschlagen, mit diesen Katastrophen zu arbeiten. Mein aktuelles Projekt ist die Migration einer umfangreichen Legacy-Webapp nach Symfony und in dieser Artikelserie möchte ich euch mit auf die abenteuerliche Reise nehmen, mit Legacy-Code zu arbeiten. Werdet mit mir zu Legacy-Code-Archäolog:innen!
Im folgenden möchte ich ein paar der Themen anreißen, mit denen ich mich näher in dieser Artikelserie beschäftigen möchte.
Was ist Legacy-Code überhaupt?
Beginnen wir doch einfach ganz logisch mit der Frage, was Legacy-Code denn überhaupt ist. Legacy-Code ist nicht unbedingt immer gleichzusetzen mit schlechtem Code. Code wird mit der Zeit beinahe unweigerlich zu Legacy-Code, auch wenn er noch so wartbar, objektorientiert und sauber mit Patterns umgesetzt ist. Wenn du dein momentanes Unternehmen verlässt oder dein Open-Source-Projekt nicht mehr weiterpflegst haben die nächsten Entwickler:innen, die sich eventuell damit beschäftigen müssen, Legacy-Code vor sich.
Damit möchte ich mich aber gar nicht so sehr beschäftigen. Mir geht es hier tatsächlich eher um die Definition des Legacy-Codes als zumindest nicht ganz optimalen Code, der historisch gewachsen ist. Wir gehen von einem Projekt aus, das aus einem recht einfachen Grundsystem zu einem großen Monster geworden ist, das kaum noch wartbar und schon gar nicht mehr erweiterbar ist, aber noch immer laufen muss, weil es noch einen Nutzen und Nutzer:innen hat, weil es noch aktiv zum Erfolg eines Unternehmens beiträgt.
Legacy-Code ist also die Hinterlassenschaft, um die du dich kümmern musst und in die einen Weg zu finden, deine nächste Aufgabe darstellt.
Legacy-PHP-Code
PHP hat sich seitdem ich mit PHP 3 angefangen habe, stark verändert. Es gibt Legacy-Systeme, denen sieht kann jede Neuerung neuer PHP-Versionen angesehen werden - dies sind dann über Jahrzehnte gewachsene Systeme, die vielleicht von vielen Entwicklern vorangetrieben wurden. Ob es andere Sprachen gibt, die sich ähnlich stark im Laufe der Zeit verändert und vor allem auch verbessert haben, kann ich nicht sagen. Aber der Sprung, den PHP von einem Web-Handwerkskasten (PHP 3) zu einer langsam erwachsenen Programmiersprache (PHP 8.*) gemacht hat, ist schon beeindruckend.
Dennoch finden wir vor allem im Legacy-Code noch viele Dinge, die es nicht einfach machen, das System zu modernisieren. Spaghetti-Code, globale Variablen, keine Typsicherheit, Frickel-Mentalität der Entwickler und die Tatsache, dass viele der alten System von Programmier-Einzelkämpfern erstellt wurden - all das macht die Arbeit mit Legacy-PHP-Code nicht einfach.
Bitte korrigiert mich, falls ich hier falsch liege, aber ich habe in keiner anderen Programmiersprache von so vielen auch sehr großen Projekten gehört, die von einem einzelnen Entwickler programmiert wurden. Und dies immer gegen die Uhr und mit Vorgesetzten, die schnell immer komplexere Features implementiert haben wollten, damit das Projekt am Markt existieren kann. Dies führt natürlich unweigerlich zu suboptimalem Code.
Auch bei mir war das so. Als Einzelkämpfer musste ich Dinge entwickeln, die eigentlich für ein Team gedacht und mit so wenig Zeitspielraum angesetzt waren, dass es quasi unmöglich war, sauberen und wartbaren Code zu schreiben. Und natürlich war es mir peinlich, so etwas zu hinterlassen.
Wege in den Legacy-Code
Wenn du engagiert wirst, dich mit einem Legacy-System zu beschäftigen, hast du mit etwas Glück noch den oder die Original-Entwickler:innen mit im Team. Allzu oft kommt es natürlich auch vor, dass du niemanden mehr hast, dem du Fragen stellen kannst und der dich bei der Einarbeitung an die Hand nimmt. Natürlich ist es äußerst hilfreich, jemanden an der Seite zu haben, der den Code gut kennt und auch die Eigenheiten beschreiben kann. Eines kann dir aber niemand abnehmen: wenn du am System arbeiten möchtest, musst du das System verstehen - und einen Weg finden, in den Code einzusteigen.
Dabei gibt es unterschiedliche Wege, mit der Expedition in den Code zu starten, also Code-Archäologie zu betreiben:
- beginne mit einzelnen Routen, die dich besonders interessieren und arbeite dich von Route zu Route vor
- verwende einen geeigneten Static Code Analyzer, um Einstiegspunkte zu finden
- suche dir relativ zufällig eine Datei aus und arbeite dich von dort aus vor
Eine Kombination aus diesen Methoden kann gut zum Ziel führen - es hängt allerdings stark davon ab, wie der Legacy-Code aufgebaut ist: besteht er viel aus Spaghetti-Code, wird wild mit include
und require
gearbeitet, ist die Architektur bereits objektorientiert, oder werden einfach nur Klassen irgendwie verwendet, basiert der Code vielleicht schon auf irgendein Framework, oder ist es eine wilde Mixtur aus allem?
An dieser Stelle wird sich bald ein Link befinden, der zu einem Artikel führt, der sich genauer mit Wegen in den Legacy-Code befasst.
Wege aus dem Legacy-Code
Hast du einen Weg in den Legacy-Code gefunden und ihn entsprechend gut verstanden? Dann musst du einen passenden Weg aus dem Legacy-Code finden.
Es kann Legacy-Systeme geben, die können einfach parallel ganz neu entwickelt werden. Ist das neue System fertig, schaltet man einfach von altem auf neues System um - fertig. Das sind dann vermutlich aber Projekte, die sehr klein und überschaubar sind und gar nicht so sehr in die Kategorie "nicht mehr wart- und erweiterbar" fallen.
Die wirklich vertrackten Legacy-Projekte, die festgefahren sind und damit am meisten Spaß machen, können meist nicht mit einer solchen Big-Bang-Umstellung abgelöst werden. Die Parallel-Entwicklung würde entweder nie fertig werden, oder die Big-Bang-Umstellung führt zu großen Problem. Solche Modernisierungsprojekte scheitern leider sehr oft.
Zum Glück gibt es mehrere Möglichkeiten, ein Legacy-Projekt erfolgreich in ein neues System zu überführen, die weg vom Big Bang und mehr in Richtung eines evolutionären Ansatz gehen:
- schrittweises Refactoring, indem der Code Stück für Stück, Modul für Modul, Komponente für Komponente verbessert und erneuert wird
- Umsetzung durch das Strangler Fig Pattern
An dieser Stelle wird sich bald ein Link befinden, der zu einem Artikel führt, der sich genauer mit Wegen aus dem Legacy-Code befasst.
Das Mindset eines Legacy-Code-Archäologen
Was macht dich zu einem guten (oder überhaupt geeigneten) Code-Archäologen? Die Arbeit mit Legacy-Code ist sicherlich nicht für alle Entwickler:innen geeinget! Vielleicht braucht man eine gewisse Art von Code-Masochismus, um die Arbeit mit und am Legacy-Code zu lieben. Ganz unbedingt solltest du aber immer neugierig sein und große Freude am Lösen von komplexen Problemen haben. Du solltest in gewisser Weise auch belastbar sein, weil die Arbeit am Legacy-Code anstrengend und mitunter auch frustrierrend sein kann. Auch Geduld ist ein guter Ratgeber, da es unter Umständen recht lange dauern kann, bis der Knoten platzt und du den Legacy-Code zumindest so gut verstanden hast, dass du damit arbeiten kannst.
Du solltest einen Sinn dafür haben, eine gesunde Balance aus Bewahren und Erneuern zu finden. Bei der Migration von Legacy-Code ist es nicht immer sinnvoll, eine 100%-Lösung anzustreben. Bestimmte bereiche müssen eventuell gar nicht migriert oder erneuert werden und können bleiben wie sie sind.
Gerade wenn du im Team arbeitest und der/die Original-Entwickler:innen noch mit im Team sind, solltest du immer verstehen, wie der Code so wurde, wie er ist. Auch wenn er in deinen Augen sehr schlecht ist heißt das nicht, dass schlechte Entwickler:innen ihn geschrieben haben! Behandle also niemanden von oben herab - das Legacy-System ist euer gemeinsamer Endgegner, den ihr nur im Team besiegen könnt!
Nicht zuletzt solltest du gern etwas neues lernen, denn eines ist gewiss: viel lernen wirst du!
Möchtest du benachrichtigt werden, sobald ein neuer Artikel erscheint? Dann schreib mir eine Mail an hello@marcuskober.de.