Definition
RefactoringW
Unter dem Begriff Refactoring versteht man - einfach gesprochen - das "Aufräumen" von Quelltext. Das Verhalten des Programms oder des Algorithmus darf dabei nicht verändert werden.
Entfernung von Redundanzen
Refactoring kann bedeuten, dass man redundanten Quelltext entfernt und auslagert.
Einfaches Beispiel
Vorher:
public class Beispiel { public void druckeBegruessung() { System.out.println("=== Start ==="); System.out.println("Willkommen!"); System.out.println("============"); } public void druckeAbschied() { System.out.println("=== Start ==="); System.out.println("Auf Wiedersehen!"); System.out.println("============"); } }
Nachher:
public class Beispiel { private void druckeMitRahmen(String text) { System.out.println("=== Start ==="); System.out.println(text); System.out.println("============"); } public void druckeBegruessung() { druckeMitRahmen("Willkommen!"); } public void druckeAbschied() { druckeMitRahmen("Auf Wiedersehen!"); } }
Ergebnis: Der gemeinsame (redundante) Code wurde in eine private Hilfsmethode druckeMitRahmen() ausgelagert. Dadurch ist der Code nicht unbedingt kürzer, aber leichter wartbar. Wenn sich jetzt die Anforderungen an die äußere Form der Ausgabe ändern, muss nur noch die private Hilfsmethode angepasst werden.
Prinzip der alleinigen Verantwortung
Ein wichtiges Prinzip der OOP besagt, dass eine Methode immer nur eine einzige Aufgabe erfüllen soll, das dann aber sehr gut und fehlerfrei. Durch gutes Refactoring kann man lange Methoden so umbauen, dass dieses Prinzip eingehalten wird.
Hier ein Code-Beispiel, das von ChatGPT generiert wurde.
Beispiel von ChatGPT 5.0
Vorher:
public class Bestellung { private Kunde kunde; private java.util.ListartikelListe; public void verarbeiteBestellung() { // Eingabe prüfen if (kunde == null || artikelListe.isEmpty()) { System.out.println("Bestellung unvollständig!"); return; } // Gesamtpreis berechnen double summe = 0; for (Artikel a : artikelListe) { summe += a.getPreis(); } // Zahlung verarbeiten System.out.println("Zahlung über " + summe + " Euro verbucht."); } }
Nachher:
public class Bestellung { private Kunde kunde; private java.util.ListartikelListe; public void verarbeiteBestellung() { if (!eingabePruefen()) return; double summe = berechneGesamtpreis(); verarbeiteZahlung(summe); } private boolean eingabePruefen() { if (kunde == null || artikelListe.isEmpty()) { System.out.println("Bestellung unvollständig!"); return false; } return true; } private double berechneGesamtpreis() { double summe = 0; for (Artikel a : artikelListe) { summe += a.getPreis(); } return summe; } private void verarbeiteZahlung(double betrag) { System.out.println("Zahlung über " + betrag + " Euro verbucht."); } }
Vorher erfüllte die Methode verarbeiteBestellung() gleich drei Aufgaben:
- Prüfung der Eingabe
- Berechnung des Gesamtpreises
- Verarbeitung der Zahlung
Eine Methode sollte aber nur eine einzige Verantwortung haben bzw. nur eine Aufgabe erfüllen und nicht drei. Durch das Refactoring wurde die Methode in drei einfachere Methoden mit jeweils nur einer Aufgabe aufgeteilt.
Zwar ist der Quelltext dadurch länger geworden, er ist aber deutlich übersichtlicher und vor allem leichter zu warten. Vor allem das Testen ist jetzt leichter geworden, weil jede Aufgabe unabhängig von den anderen getestet werden kann.
Quellen:
- Lahres et al.: Objektorientierte Programmierung, Rheinwerk Computing 2021.
- Barnes, Kölling: Java lernen mit BlueJ - Objects first. Pearson-Verlag 2019.
- Ullenboom: Java ist auch eine Insel, Rheinwerk Computing 2023.