Refactoring

Refactoring ist der systematische Prozess der Umstrukturierung von bestehendem Quellcode ohne Änderung seines externen Verhaltens, um Lesbarkeit, Wartbarkeit und Erweiterbarkeit zu verbessern.

Auf dieser Seite

Refactoring bezeichnet den systematischen Prozess der Umstrukturierung von bestehendem Quellcode, ohne dessen externes Verhalten zu verändern. Das Ziel ist die Verbesserung der internen Codequalität: bessere Lesbarkeit, einfachere Wartbarkeit und höhere Erweiterbarkeit. Der Begriff wurde maßgeblich durch Martin Fowlers gleichnamiges Buch von 1999 geprägt.

Refactoring ist wie das Aufräumen und Umorganisieren einer Werkstatt: Die Werkzeuge und Materialien bleiben dieselben, aber durch bessere Anordnung kann man effizienter arbeiten. In der Softwareentwicklung bedeutet das: Der Code macht weiterhin dasselbe, aber Entwickler können ihn leichter verstehen, warten und erweitern.

Warum ist Refactoring wichtig?

Software entwickelt sich ständig weiter. Mit jeder neuen Funktion, jedem Bugfix und jeder Änderung wächst die Codebasis. Ohne regelmäßiges Refactoring sammelt sich sogenannte technische Schuld an, der Code wird immer schwerer verständlich und wartbar. Refactoring ist die Lösung, um diese Schuld systematisch abzubauen.

Die wichtigsten Vorteile von Refactoring:

  • Bessere Lesbarkeit: Klare Strukturen und aussagekräftige Namen machen den Code verständlicher
  • Einfachere Wartung: Gut strukturierter Code lässt sich schneller ändern und debuggen
  • Weniger Fehler: Reduzierte Komplexität führt zu weniger Bugs
  • Höhere Entwicklungsgeschwindigkeit: Langfristig arbeitet das Team schneller mit sauberem Code
  • Bessere Testbarkeit: Kleine, fokussierte Methoden sind leichter zu testen

Die wichtigsten Refactoring-Techniken

Martin Fowler hat in seinem Standardwerk einen Katalog von Refactoring-Techniken zusammengestellt. Diese Techniken sind kleine, bewährte Transformationen, die einzeln oder kombiniert angewendet werden können.

Extract Method

Extract Method ist eine der häufigsten Refactoring-Techniken. Sie wird angewendet, wenn eine Methode zu lang ist oder einen Codeblock enthält, der einen eigenständigen Zweck erfüllt. Der Block wird in eine neue Methode mit aussagekräftigem Namen ausgelagert.

// Vorher: Lange Methode mit gemischten Verantwortlichkeiten
public void processOrder(Order order) {
    // Validierung
    if (order.getItems().isEmpty()) {
        throw new IllegalArgumentException("Bestellung ist leer");
    }
    if (order.getCustomer() == null) {
        throw new IllegalArgumentException("Kein Kunde angegeben");
    }
    
    // Preisberechnung
    double total = 0;
    for (Item item : order.getItems()) {
        total += item.getPrice() * item.getQuantity();
    }
    order.setTotal(total);
    
    // Speichern
    orderRepository.save(order);
}

// Nachher: Klare Struktur durch Extract Method
public void processOrder(Order order) {
    validateOrder(order);
    calculateTotal(order);
    orderRepository.save(order);
}

private void validateOrder(Order order) {
    if (order.getItems().isEmpty()) {
        throw new IllegalArgumentException("Bestellung ist leer");
    }
    if (order.getCustomer() == null) {
        throw new IllegalArgumentException("Kein Kunde angegeben");
    }
}

private void calculateTotal(Order order) {
    double total = 0;
    for (Item item : order.getItems()) {
        total += item.getPrice() * item.getQuantity();
    }
    order.setTotal(total);
}

Rename

Gute Namen sind entscheidend für verständlichen Code. Die Rename-Technik ändert Bezeichner (Variablen, Methoden, Klassen) in aussagekräftigere Namen. Moderne IDEs unterstützen sicheres Umbenennen im gesamten Projekt.

// Vorher: Unklare Bezeichner
function calc(a, b, c) {
    return a * b * (1 - c);
}

// Nachher: Selbsterklärender Code
function calculateDiscountedPrice(price, quantity, discountRate) {
    return price * quantity * (1 - discountRate);
}

Move Method / Move Field

Manchmal befindet sich eine Methode oder ein Feld in der falschen Klasse. Die Move-Technik verschiebt sie dorthin, wo sie konzeptuell hingehört. Ein typisches Anzeichen: Eine Methode verwendet mehr Daten einer anderen Klasse als der eigenen.

Weitere wichtige Techniken

TechnikBeschreibungAnwendungsfall
Inline MethodErsetzt Methodenaufruf durch den MethodeninhaltWenn die Methode trivial ist und der Name nichts hinzufügt
Extract ClassTeilt eine große Klasse in mehrere kleinereKlasse hat zu viele Verantwortlichkeiten
Replace Temp with QueryErsetzt temporäre Variable durch MethodenaufrufBerechnung soll wiederverwendbar sein
Introduce Parameter ObjectFasst mehrere Parameter zu einem Objekt zusammenMethode hat zu viele Parameter
Encapsulate FieldMacht Feld privat und fügt Getter/Setter hinzuDirekter Feldzugriff von außen

Code Smells erkennen

Code Smells sind Hinweise darauf, dass Refactoring nötig sein könnte. Sie sind keine Fehler im eigentlichen Sinne, der Code funktioniert ja, aber sie deuten auf tieferliegende Designprobleme hin. Das Erkennen von Code Smells ist der erste Schritt zum gezielten Refactoring.

Häufige Code Smells:

  • Long Method: Methoden mit mehr als 20-30 Zeilen sind oft zu lang
  • Large Class: Klassen mit zu vielen Verantwortlichkeiten
  • Duplicate Code: Derselbe oder ähnlicher Code an mehreren Stellen
  • Feature Envy: Eine Methode nutzt mehr Daten einer anderen Klasse als der eigenen
  • Primitive Obsession: Verwendung primitiver Typen statt kleiner Objekte (z.B. String für E-Mail-Adressen)
  • Data Clumps: Datengruppen, die immer zusammen auftreten
  • Comments: Übermäßige Kommentare können auf unklaren Code hindeuten

Refactoring vs. Rewriting

Refactoring wird oft mit Rewriting (Neuschreiben) verwechselt. Der entscheidende Unterschied: Beim Refactoring bleibt der existierende Code erhalten und wird schrittweise verbessert. Beim Rewriting wird der Code komplett neu geschrieben.

AspektRefactoringRewriting
VorgehenKleine, inkrementelle SchritteKompletter Neubeginn
RisikoGering (schrittweise Validierung)Hoch (Big-Bang-Ansatz)
ZeitaufwandKontinuierlich, verteiltGroßes Vorab-Investment
FunktionalitätBleibt während des Prozesses erhaltenErst am Ende wieder verfügbar
AnwendungsfallNormale CodequalitätsproblemeFundamentale Architekturprobleme

Die Faustregel: Refactoring ist fast immer die bessere Wahl. Rewriting sollte nur bei fundamentalen Architekturproblemen in Betracht gezogen werden, etwa wenn die verwendete Technologie veraltet ist oder die Grundstruktur nicht mehr zu den Anforderungen passt.

Best Practices für erfolgreiches Refactoring

Damit Refactoring sicher und effektiv ist, solltest du einige bewährte Praktiken beachten:

1. Tests sind Pflicht

Vor dem Refactoring muss eine ausreichende Testabdeckung vorhanden sein. Tests stellen sicher, dass das Verhalten des Codes nach dem Refactoring unverändert bleibt. Der Red-Green-Refactor-Zyklus aus dem Test-Driven Development (TDD) integriert Refactoring direkt in den Entwicklungsprozess.

2. Kleine Schritte machen

Refactoring sollte in kleinen, atomaren Schritten erfolgen. Nach jeder Änderung werden die Tests ausgeführt. So lassen sich Fehler sofort lokalisieren. Eine gute Faustregel: Zwischen zwei Testläufen sollten maximal fünf Minuten Arbeit liegen.

3. Versionskontrolle nutzen

Nutze Git oder ein anderes Versionskontrollsystem. Erstelle separate Branches für größere Refactorings und committe häufig. So kannst du jederzeit zu einem funktionierenden Zustand zurückkehren.

4. Das Boy-Scout-Prinzip

“Hinterlasse den Code besser, als du ihn vorgefunden hast.” Statt große Refactoring-Projekte zu planen, verbessere den Code kontinuierlich bei jeder Änderung. Wenn du einen Bugfix machst oder ein Feature hinzufügst, räume nebenbei ein wenig auf.

Tool-Unterstützung

Moderne Entwicklungsumgebungen bieten umfangreiche Unterstützung für automatisiertes Refactoring. Diese Tools führen die Transformationen sicher durch und aktualisieren alle betroffenen Stellen im Projekt.

IDE-Integration:

  • IntelliJ IDEA: Umfangreiche Refactoring-Funktionen für Java, Kotlin und andere Sprachen
  • Visual Studio: Refactoring-Support für C#, .NET und weitere
  • Visual Studio Code: Erweiterungen für verschiedene Sprachen
  • Eclipse: Klassische Java-IDE mit soliden Refactoring-Tools

Analyse-Tools:

  • SonarQube: Erkennt Code Smells und schlägt Verbesserungen vor
  • ESLint / TSLint: Regelbasierte Analyse für JavaScript/TypeScript
  • PMD / Checkstyle: Statische Analyse für Java

Refactoring in der Ausbildung

Für angehende Fachinformatiker für Anwendungsentwicklung ist Refactoring eine zentrale Kompetenz. In der Praxis verbringst du oft mehr Zeit mit dem Lesen und Ändern von bestehendem Code als mit dem Schreiben von neuem Code. Refactoring-Fähigkeiten helfen dir dabei:

  • Legacy-Code zu verstehen und zu verbessern
  • Wartbare Software zu entwickeln, die auch nach Jahren noch erweiterbar ist
  • Im Team effektiv zusammenzuarbeiten durch lesbaren Code
  • Technische Schulden zu erkennen und abzubauen
  • Professionelle Entwicklungspraktiken anzuwenden

Übe Refactoring regelmäßig, zum Beispiel mit Coding Katas wie FizzBuzz, wo du zunächst eine funktionierende Lösung schreibst und diese dann schrittweise verbesserst. So entwickelst du ein Gespür dafür, wann und wie Code verbessert werden kann.

Prüfungsbezug

Passt zu deiner Prüfungsvorbereitung

Wenn dir dieser Begriff in Aufgaben, Projektdokumentation oder Fachgespräch begegnet, ordne ihn direkt in den Prüfungsstoff ein.