Simyl
simylflow
Kursübersicht
Modul 2: Technische Praktiken
Lektion 3 von 5
12 Min.

Refactoring

Code verbessern, ohne zu ändern, was er tut. Die Disziplin, die Codebasen gesund hält.

1Was Refactoring ist (und was nicht)

Refactoring bedeutet, die interne Struktur von Code zu verbessern, ohne sein externes Verhalten zu ändern.

Diese Definition hat zwei entscheidende Teile:

Struktur verbessern: Code verständlicher, änderbar oder erweiterbarer machen. Dazu gehören bessere Namen, kleinere Funktionen, klarere Organisation, weniger Duplikate.

Ohne Verhaltensänderung: Der Code tut genau das, was er vorher getan hat. Eingaben erzeugen dieselben Ausgaben. Seiteneffekte sind identisch. Tests bestehen weiterhin.

Refactoring ist nicht:

  • Von Grund auf neu schreiben
  • Features hinzufügen
  • Bugs beheben
  • Performance-Optimierung (normalerweise)

Wenn du änderst, was der Code tut, refaktorierst du nicht – du machst etwas anderes. Refactoring betrifft speziell die Struktur, nicht das Verhalten.

Refactoring ist wie deine Küche aufräumen. Das Essen schmeckt gleich. Aber Kochen wird einfacher, schneller und weniger frustrierend.

2Der Refactoring-Katalog

Martin Fowler dokumentierte Dutzende spezifischer Refactorings, jedes mit:

  • Einem Namen (damit Teams kommunizieren können)
  • Einer Motivation (wann man es verwendet)
  • Mechanik (Schritt-für-Schritt-Anleitung zur sicheren Durchführung)

Hier sind einige, die du ständig verwenden wirst:

Extract Function: Nimm etwas Code und packe ihn in eine neue Funktion mit einem klaren Namen. Das ist wahrscheinlich das häufigste Refactoring.

Rename: Ändere den Namen einer Variable, Funktion oder Klasse, um ihren Zweck besser auszudrücken. Gute Namen sind überraschend wichtig.

Inline Function: Das Gegenteil von Extract – ersetze einen Funktionsaufruf durch seinen Inhalt. Verwende es, wenn eine Funktion keine Klarheit hinzufügt.

Extract Variable: Nimm einen komplexen Ausdruck und gib ihm einen Namen, indem du ihn einer Variable zuweist.

Move Function: Verschiebe eine Funktion zu einer Klasse, wo sie mehr Sinn ergibt.

Replace Conditional with Polymorphism: Ersetze komplexe if/else- oder switch-Anweisungen durch objektorientiertes Dispatch.

Das sind keine "fortgeschrittenen" Refactorings. Es sind alltägliche Werkzeuge. Lerne sie, bis sie automatisch sind.

3Sicher refaktorieren

Refactoring ist nur sicher, wenn du Tests hast. Ohne Tests könnte jede Änderung etwas kaputt machen, und du erfährst es erst in der Produktion.

Der Sicherheitsprozess:

  1. Stelle sicher, dass Tests vor dem Start bestehen
  2. Mache eine kleine Änderung
  3. Führe Tests aus
  4. Wenn Tests bestehen, weitermachen; wenn sie fehlschlagen, sofort zurücksetzen
  5. Wiederholen

Kleine Schritte sind entscheidend. Versuche nicht, fünf Dinge auf einmal zu refaktorieren. Extrahiere eine Funktion, führe Tests aus, committe. Benenne eine Variable um, führe Tests aus, committe. So weißt du genau, was es verursacht hat, wenn etwas kaputt geht.

Moderne IDEs haben automatisierte Refactorings, die sicherer sind als manuelle Änderungen. "Rename" in deiner IDE aktualisiert alle Referenzen. "Extract Function" erstellt die Funktion und aktualisiert die Aufrufstelle. Nutze diese Werkzeuge.

Die Pfadfinderregel: Hinterlasse den Code besser, als du ihn vorgefunden hast. Wenn du Code aus irgendeinem Grund anfasst, mache eine kleine Verbesserung. Mit der Zeit wird die Codebasis sauberer statt schmutziger.

Keine Tests = Keine Sicherheit

Refactoring ohne Tests ist nur Code ändern und hoffen. Es ist kein Refactoring – es ist Glücksspiel.

4Wann refaktorieren

Refaktoriere ständig. Refactoring ist keine separate Phase oder Sprint. Es ist kontinuierlich.

Spezifische Auslöser zum Refaktorieren:

Vor dem Hinzufügen eines Features: Wenn die aktuelle Struktur das Feature schwer hinzuzufügen macht, refaktoriere zuerst. Mache die Änderung einfach, dann mache die einfache Änderung.

Nachdem ein Test besteht: Das ist das "Refactor" in Rot-Grün-Refactor. Räume auf, bevor du zum nächsten Test übergehst.

Wenn du einen Code Smell bemerkst: Duplizierter Code, lange Methoden, unklare Namen, komplexe Bedingungen – das sind Signale, dass Refactoring nötig ist.

Während Code Review: Wenn du etwas siehst, das du verbessern würdest, mache es entweder oder notiere es für später.

Wenn du Zeit hast: Habe ein "Refactoring-Backlog" bekannter Probleme. Wenn du Luft hast, nimm etwas von der Liste.

Refaktoriere nicht, wenn:

  • Du keine Tests hast
  • Du kurz vor dem Release stehst (stabilisiere, ändere nicht)
  • Du nicht verstehst, was der Code tut (verstehe zuerst)

5Technical Debt und Refactoring

Technical Debt sind die akkumulierten Kosten von Abkürzungen. Jedes Mal, wenn du sagst "Ich räume das später auf" und es nicht tust, fügst du Schulden hinzu. Jedes Mal, wenn du kopierst und einfügst, statt zu extrahieren, fügst du Schulden hinzu.

Schulden sammeln Zinsen an. Unordentlicher Code braucht länger zum Ändern. Bugs verstecken sich in Komplexität. Neue Teammitglieder haben Schwierigkeiten zu verstehen. Die Kosten für Änderungen steigen.

Refactoring ist, wie du Schulden abbezahlst. Regelmäßiges Refactoring hält Schulden handhabbar. Refactoring zu vernachlässigen lässt Schulden sich aufschaukeln, bis die Codebasis unbrauchbar wird.

Die zentrale Erkenntnis: Refactoring ist kein Luxus. Es ist essentielle Wartung. Du fragst nicht um Erlaubnis, Schulden abzubezahlen – du machst es einfach als Teil deiner Arbeit.

XP baut Refactoring in den Prozess ein. Jedes Feature, jeder Bugfix, jede Aufgabe beinhaltet Zeit, den Code besser zu hinterlassen, als du ihn vorgefunden hast. Du brauchst keinen "Refactoring-Sprint" – du brauchst eine Refactoring-Gewohnheit.

Gute Refactoring-Praxis

Beim Beheben eines Bugs bemerkst du duplizierten Code in der Nähe. Du behebst zuerst den Bug (Verhaltensänderung), dann extrahierst du die Duplikation in eine Funktion (Refactoring). Zwei Commits: Bugfix, dann Refactoring.

Refactoring schief gelaufen

Während du ein Feature hinzufügst, beschließt du auch, das Authentifizierungssystem zu refaktorieren, die Ordnerstruktur neu zu organisieren und das Datenbankschema zu aktualisieren. Du verlierst den Überblick, was sich geändert hat, Tests schlagen mysteriös fehl, und du verbringst Stunden mit Debugging.

Wichtige Erkenntnisse
  • Refactoring verbessert Code-Struktur ohne Verhaltensänderung
  • Tests sind essentiell – Refactoring ohne Tests ist nur Code ändern und hoffen
  • Mache kleine Schritte: eine Änderung, Tests ausführen, wiederholen
  • Nutze die Pfadfinderregel: hinterlasse Code besser, als du ihn vorgefunden hast
  • Refactoring ist fortlaufend, keine separate Phase – baue es in die tägliche Arbeit ein
Häufige Fehler, die es zu vermeiden gilt
  • Refactoring und Features gleichzeitig hinzufügen (mache eins oder das andere)
  • Big-Bang-Refactoring statt kleiner Schritte
  • Refactoring ohne Tests (zu riskant)
  • Um Erlaubnis zum Refaktorieren fragen (es ist Teil der Arbeit)

Praxisübungen