Strukturieren mit Methoden
Dieses Kapitel basiert auf dem Arbeitsblatt "Strukturieren mit Methoden". Die Ausgangsidee dort ist sehr klar: Ein funktionierender, aber monolithischer Quelltext soll so umgebaut werden, dass mehrere kleine, gut benannte Hilfsmethoden entstehen.
Warum Strukturierung mehr ist als Schoenheit
Viele Einsteigerprogramme laufen zwar korrekt, sind aber schwer lesbar und kaum erweiterbar. Ursachen sind oft:
- zu lange Methoden
- gemischte Verantwortlichkeiten
- schwer testbare Einzelschritte
Die Zerlegung in Teilmethoden verbessert:
- Lesbarkeit
- Testbarkeit
- Wiederverwendbarkeit
- Fehlersuche
Ausgangsbeispiel aus dem Arbeitsblatt
Das Blatt verwendet eine Klasse StatistikBerechner, in der eine Methode berechneStatistiken(int[] zahlen) alles auf einmal erledigt:
- Eingabe pruefen
- Summe berechnen
- Minimum bestimmen
- Maximum bestimmen
- Durchschnitt berechnen
- Ausgabe erzeugen
Didaktisch ist genau das der richtige Startpunkt fuer Refactoring.
Zielstruktur laut Aufgabenstellung
Das Arbeitsblatt fordert konkret diese Hilfsmethoden:
private int berechneSumme(int[] zahlen)private double berechneDurchschnitt(int[] zahlen, int summe)private int[] berechneMinUndMax(int[] zahlen)private void ausgabeStatistiken(int summe, double durchschnitt, int minimum, int maximum)
Diese Signaturen zeigen bereits ein gutes Prinzip: Jede Methode bekommt eine eindeutige Verantwortung.
Refactoring-Schritt fuer Refactoring-Schritt
Schritt 1: Eingabepruefung klar isolieren
Die Hauptmethode sollte frueh entscheiden, ob gerechnet werden kann.
if (zahlen == null || zahlen.length == 0) {
System.out.println("Keine Daten verfuegbar.");
return;
}
Damit sind Randfaelle sofort abgearbeitet.
Schritt 2: Berechnungen auslagern
Alle mathematischen Teilaufgaben in private Methoden verschieben.
private int berechneSumme(int[] zahlen) {
int summe = 0;
for (int z : zahlen) {
summe += z;
}
return summe;
}
Schritt 3: Zusammensetzen in Hauptmethode
Die Hauptmethode beschreibt danach nur noch den Ablauf.
public void berechneStatistiken(int[] zahlen) {
if (zahlen == null || zahlen.length == 0) {
System.out.println("Keine Daten verfuegbar.");
return;
}
int summe = berechneSumme(zahlen);
double durchschnitt = berechneDurchschnitt(zahlen, summe);
int[] minMax = berechneMinUndMax(zahlen);
ausgabeStatistiken(summe, durchschnitt, minMax[0], minMax[1]);
}
Das ist deutlich leichter zu lesen als die monolithische Variante.
Gute Methodennamen als Dokumentation
Im Arbeitsblatt wird indirekt ein zentraler Stilpunkt trainiert: Methodenname soll die Absicht beschreiben.
Gut:
berechneSummeberechneDurchschnittausgabeStatistiken
Schwach:
mach1helperrunStuff
Je klarer Namen sind, desto weniger Kommentare braucht der Code.
Private Hilfsmethoden und Kapselung
Dass die Zielmethoden private sind, ist kein Zufall.
- Sie sind interne Bausteine.
- Externe Klassen sollen sie nicht direkt aufrufen.
- Oeffentliche API bleibt klein und stabil.
Das ist sauberes Klassen-Design.
Zusatzeffekt: einfachere Tests
Kleine Methoden lassen sich gezielter testen.
Beispiele:
berechneSumme({1,2,3}) == 6berechneMinUndMax({7,2,9}) -> {2,9}berechneDurchschnitt({2,4,6}, 12) == 4.0
Wenn ein Test fehlschlaegt, ist sofort klar, welcher Teilschritt betroffen ist.
Robustheit bei Randfaellen
Refactoring ist eine gute Gelegenheit, Randfaelle bewusst mitzunehmen:
null- leeres Array
- sehr grosse Werte
- negative Werte
- alle Werte identisch
Diese Faelle sollten in den Methodenvertraegen klar sein.
Strukturierungsprinzipien aus dem Kapitel
- Eine Methode, eine Hauptverantwortung.
- Wiederholte Logik in Hilfsmethoden auslagern.
- Hauptablauf als gut lesbare Choreografie schreiben.
- Interne Hilfsmethoden als
privatekapseln. - Fruehe Gueltigkeitspruefung statt spaeter Fehler.
Uebertragung auf andere Aufgaben
Das Blatt nennt als weiteres Szenario die Auswertung von Kundendaten (z. B. nach Gruppen getrennt).
Auch dort ist die Struktur identisch:
- vorbereiten
- aufteilen
- gruppenweise berechnen
- Ergebnis ausgeben
Diese Form der Zerlegung ist fachunabhaengig und daher sehr wertvoll.
Typische Antimuster
- Monster-Methode Eine Methode mit 80+ Zeilen und mehreren Aufgaben.
- Copy-Paste statt Auslagern Aehnliche Berechnung mehrfach mit kleinen Abweichungen.
- Ausgabe und Berechnung untrennbar vermischt Schwer testbar.
- Unklare Parameter Methoden brauchen zu viele oder missverstaendliche Eingaben.
- Zu frueh zu feingranular Nicht jede Dreizeiler-Hilfsmethode ist automatisch besser.
Erweiterte Uebungen
- Refaktoriere eine Methode
analysiereNoten(int[] noten)analog zu diesem Kapitel. - Trenne reine Berechnung von Konsolenausgabe.
- Fuehre eine Methode
validiereEingabe(int[] werte)ein. - Fuehre Tests fuer
null, leeres Array und Einzelelement ein. - Vergleiche Laufzeit und Lesbarkeit vor/nach dem Refactoring.
Zusammenfassung
Das Arbeitsblatt zeigt mit einem einfachen Statistikbeispiel einen professionellen Kernprozess:
- funktionierenden Code analysieren
- Verantwortlichkeiten trennen
- in kleine Methoden zerlegen
- Ergebnis robuster und besser testbar machen
Diese Kompetenz ist zentral fuer alle spaeteren groesseren Kapitel und Projekte.
Abbildungen
In der zugeordneten Datei wurden keine eingebetteten Bildobjekte gefunden.
Von "funktioniert" zu "wartbar"
Das Arbeitsblatt zeigt einen typischen Ist-Zustand: eine lange Methode, die korrekt rechnet, aber mehrere Aufgaben gleichzeitig uebernimmt. In der Praxis ist das ein klassischer Ausgangspunkt fuer Refactoring.
Unterscheide zwei Qualitaetsstufen:
- funktional korrekt Ergebnis stimmt fuer Testeingaben.
- strukturell wartbar Code ist lesbar, testbar und erweiterbar.
Das Kapitel trainiert den Schritt von 1 zu 2.
Verantwortungen explizit trennen
Im Statistikbeispiel lassen sich mindestens vier Verantwortungen erkennen:
- Eingabegueltigkeit pruefen
- Kennzahlen berechnen
- Ergebnis formatieren
- Ergebnis ausgeben
Wenn diese Teile in einer Methode vermischt bleiben, werden Aenderungen teuer.
Schrittweises Refactoring ohne Verhaltensaenderung
Wichtig: Refactoring soll das Verhalten nicht aendern.
Empfohlene Reihenfolge:
- Ausgangscode mit kleinen Testdaten fixieren.
- Erste Teilmethode extrahieren (z. B. Summe).
- Nach jedem Schritt erneut testen.
- Naechste Teilmethode extrahieren.
- Zum Schluss Namen und Parameter klarziehen.
So bleibt die Fehlerwahrscheinlichkeit niedrig.
Parameterdesign bei Hilfsmethoden
Im Arbeitsblatt ist berechneDurchschnitt(int[] zahlen, int summe) vorgesehen. Das zeigt ein gutes Prinzip:
- bereits berechnete Werte als Parameter weitergeben
- doppelte Arbeit vermeiden
Dadurch bleibt Komplexitaet in jeder Methode klein.
Rueckgabestrategien vergleichen
Bei berechneMinUndMax gibt es verschiedene Loesungen:
- Rueckgabe als
int[] {min, max} - kleines Hilfsobjekt
MinMax - zwei getrennte Methoden
Fuer den Einstieg ist int[] oft ausreichend. Fuer groessere Systeme ist ein benanntes Objekt lesbarer.
Ausgabe von Berechnung trennen
Eine zentrale Lehre des Blatts: Rechenmethoden sollten moeglichst nicht direkt drucken.
Besser:
- Berechnung liefert Werte
- Ausgabe passiert in eigener Methode
Vorteile:
- einfache Tests ohne Konsolenabhaengigkeit
- spaeter leicht auf GUI oder Datei umstellbar
Beispiel mit Hilfsobjekt
class Statistik {
int summe;
double durchschnitt;
int minimum;
int maximum;
}
private Statistik berechneStatistik(int[] zahlen) {
Statistik s = new Statistik();
s.summe = berechneSumme(zahlen);
s.durchschnitt = berechneDurchschnitt(zahlen, s.summe);
int[] mm = berechneMinUndMax(zahlen);
s.minimum = mm[0];
s.maximum = mm[1];
return s;
}
Dies ist kein Pflichtmuster im Blatt, aber eine sinnvolle Vertiefung fuer saubere Struktur.
Heuristik fuer Methodengroesse
Praktische Faustregel fuer Unterrichtsprojekte:
- Wenn eine Methode beim Vorlesen mehr als einen klaren Gedankengang enthaelt, sollte sie geteilt werden.
- Wenn mehrere
if-Bloecke verschiedene Aufgaben steuern, sollte umstrukturiert werden.
Ziel ist nicht kuenstliche Kleinteiligkeit, sondern klare Verantwortlichkeit.
Typische Refactoring-Fallen
- Methode extrahieren, aber Namen unklar lassen.
- Seiteneffekte beim Umzug uebersehen.
- Zu viele Parameter ohne Struktur.
- Eingabepruefung versehentlich entfernen.
- Tests erst nach vielen Schritten ausfuehren.
Das Blatt eignet sich gut, um genau diese Fallen bewusst zu besprechen.
Uebung: zweites Szenario strukturieren
Das Arbeitsblatt nennt als weiteres Beispiel eine Kundenauswertung. Eine moegliche Struktur:
zaehleGruppen(...)fuelleGruppenArrays(...)berechneDurchschnittsalter(...)druckeErgebnis(...)
Diese Uebertragung zeigt, dass Strukturierungsprinzipien nicht auf Statistikzahlen beschraenkt sind.
Code-Review-Checkliste
- Hat jede Methode genau eine Hauptaufgabe?
- Sind Methodennamen selbsterklaerend?
- Werden Randfaelle frueh behandelt?
- Sind Berechnung und Ausgabe getrennt?
- Gibt es Duplikatcode, der extrahiert werden sollte?
Diese Fragen koennen direkt in Partnerreviews genutzt werden.
Leistungsnachweis-Idee
Aufgabe:
- Gegeben ist eine 40-zeilige Methode mit gemischter Logik.
- Ziel ist Refactoring in 4 bis 6 Hilfsmethoden.
- Bewertungskriterien:
- funktional unveraendert
- bessere Lesbarkeit
- nachvollziehbare Methodennamen
- Testfaelle fuer Randbedingungen
Damit wird exakt die Kompetenz geprueft, die das Blatt aufbaut.
Transfer in Projektarbeit
In groesseren Projekten ist "Strukturieren mit Methoden" der Standardalltag:
- Features werden erweitert
- alte Methoden werden unlesbar
- Refactoring sorgt fuer langfristige Wartbarkeit
Wer diese Technik frueh lernt, spart spaeter viel Zeit bei Fehlersuche und Teamarbeit.
Abschluss der Vertiefung
Das Arbeitsblatt hat einen klaren Mehrwert: Es zeigt nicht nur, wie man Java-Code schreibt, sondern wie man vorhandenen Code verbessert, ohne Funktionalitaet zu verlieren. Diese Refactoring-Kompetenz ist ein Schluesselschritt von Einsteiger- zu professioneller Entwicklungsarbeit.
Abschlussaufgabe zum Refactoring
Gegeben ist eine absichtlich lange Methode zur Analyse von Verkaufsdaten. Refaktoriere sie in mindestens fuenf Hilfsmethoden mit klaren Namen.
Mindestanforderungen:
- Eingabevalidierung separat
- Berechnungsteil getrennt
- Ausgabe getrennt
- keine Duplikate
- Verhalten gegenueber Ausgangscode unveraendert
Dokumentiere vor und nach dem Refactoring:
- Methodenlaenge
- Anzahl Bedingungen
- Anzahl frueher Rueckgaben
Damit wird die im Arbeitsblatt trainierte Strukturierung messbar gemacht.
Pruefungsnahe Kurzfragen
- Woran erkennst du, dass eine Methode zu viele Verantwortungen hat?
- Warum sollten Hilfsmethoden meist
privatesein? - Weshalb ist die Trennung von Berechnung und Ausgabe wichtig?
- Wie stellst du sicher, dass Refactoring das Verhalten nicht veraendert?
Mit diesen Fragen laesst sich die Refactoring-Kompetenz schnell ueberpruefen.
Weiterfuehrende Praxisaufgabe
Nimm eine bestehende Methode aus deinem eigenen Projekt mit mindestens 25 Zeilen und refaktoriere sie nach diesem Schema:
- Gueltigkeitspruefung isolieren
- Hauptberechnung in Teilmethoden zerlegen
- Ausgabe/Logging trennen
- gemeinsame Teillogik zentralisieren
Dokumentiere danach kurz:
- vorherige Zeilenanzahl
- neue Methodenzahl
- welche Methoden jetzt leichter testbar sind
So wird die Kapitelidee direkt auf echten Code uebertragen.
Mini-Reflexion
Gute Strukturierung ist dann erreicht, wenn die Hauptmethode wie ein Ablaufplan gelesen werden kann und jede Hilfsmethode nur einen klaren Zweck erfuellt. Wenn das beim lauten Vorlesen nicht erkennbar ist, lohnt sich ein weiterer Refactoring-Schritt.
Zusatzaufgabe
Nimm eine vorhandene Methode aus diesem Kapitel und fuehre eine zweite Refactoringrunde nur auf Benennungsebene durch: Variablen-, Methoden- und Parameternamen sollen ohne zusaetzliche Kommentare selbsterklaerend sein. Vergleiche danach beide Versionen im direkten Code-Review.
Schlussgedanke
Strukturierung ist kein einmaliger Schritt, sondern ein kontinuierlicher Prozess. Jede neue Anforderung ist ein Anlass zu pruefen, ob die Methodenstruktur noch klar und tragfaehig ist.
Refactoring ist damit nicht nur technische Kosmetik, sondern direkte Qualitaetsarbeit an Lesbarkeit, Testbarkeit und langfristiger Veraenderbarkeit des Codes.
