Refactoring
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.
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.
Quellen und weiterführende Links
- Martin Fowler: Refactoring (2. Auflage) - Das Standardwerk zum Thema
- Refactoring.Guru - Interaktiver Katalog aller Refactoring-Techniken mit Beispielen
- Wikipedia: Refactoring - Grundlegende Übersicht
- Working Effectively with Legacy Code - Michael Feathers' Buch zum Umgang mit Altcode
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
| Technik | Beschreibung | Anwendungsfall |
|---|---|---|
| Inline Method | Ersetzt Methodenaufruf durch den Methodeninhalt | Wenn die Methode trivial ist und der Name nichts hinzufügt |
| Extract Class | Teilt eine große Klasse in mehrere kleinere | Klasse hat zu viele Verantwortlichkeiten |
| Replace Temp with Query | Ersetzt temporäre Variable durch Methodenaufruf | Berechnung soll wiederverwendbar sein |
| Introduce Parameter Object | Fasst mehrere Parameter zu einem Objekt zusammen | Methode hat zu viele Parameter |
| Encapsulate Field | Macht Feld privat und fügt Getter/Setter hinzu | Direkter 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.
| Aspekt | Refactoring | Rewriting |
|---|---|---|
| Vorgehen | Kleine, inkrementelle Schritte | Kompletter Neubeginn |
| Risiko | Gering (schrittweise Validierung) | Hoch (Big-Bang-Ansatz) |
| Zeitaufwand | Kontinuierlich, verteilt | Großes Vorab-Investment |
| Funktionalität | Bleibt während des Prozesses erhalten | Erst am Ende wieder verfügbar |
| Anwendungsfall | Normale Codequalitätsprobleme | Fundamentale 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.