Autor: HM_JDSZielgruppe: Sek I

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:

  1. Lesbarkeit
  2. Testbarkeit
  3. Wiederverwendbarkeit
  4. 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:

  • berechneSumme
  • berechneDurchschnitt
  • ausgabeStatistiken

Schwach:

  • mach1
  • helper
  • runStuff

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}) == 6
  • berechneMinUndMax({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

  1. Eine Methode, eine Hauptverantwortung.
  2. Wiederholte Logik in Hilfsmethoden auslagern.
  3. Hauptablauf als gut lesbare Choreografie schreiben.
  4. Interne Hilfsmethoden als private kapseln.
  5. 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:

  1. vorbereiten
  2. aufteilen
  3. gruppenweise berechnen
  4. Ergebnis ausgeben

Diese Form der Zerlegung ist fachunabhaengig und daher sehr wertvoll.

Typische Antimuster

  1. Monster-Methode Eine Methode mit 80+ Zeilen und mehreren Aufgaben.
  2. Copy-Paste statt Auslagern Aehnliche Berechnung mehrfach mit kleinen Abweichungen.
  3. Ausgabe und Berechnung untrennbar vermischt Schwer testbar.
  4. Unklare Parameter Methoden brauchen zu viele oder missverstaendliche Eingaben.
  5. Zu frueh zu feingranular Nicht jede Dreizeiler-Hilfsmethode ist automatisch besser.

Erweiterte Uebungen

  1. Refaktoriere eine Methode analysiereNoten(int[] noten) analog zu diesem Kapitel.
  2. Trenne reine Berechnung von Konsolenausgabe.
  3. Fuehre eine Methode validiereEingabe(int[] werte) ein.
  4. Fuehre Tests fuer null, leeres Array und Einzelelement ein.
  5. 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:

  1. funktional korrekt Ergebnis stimmt fuer Testeingaben.
  2. 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:

  1. Eingabegueltigkeit pruefen
  2. Kennzahlen berechnen
  3. Ergebnis formatieren
  4. 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:

  1. Ausgangscode mit kleinen Testdaten fixieren.
  2. Erste Teilmethode extrahieren (z. B. Summe).
  3. Nach jedem Schritt erneut testen.
  4. Naechste Teilmethode extrahieren.
  5. 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:

  1. Rueckgabe als int[] {min, max}
  2. kleines Hilfsobjekt MinMax
  3. 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

  1. Methode extrahieren, aber Namen unklar lassen.
  2. Seiteneffekte beim Umzug uebersehen.
  3. Zu viele Parameter ohne Struktur.
  4. Eingabepruefung versehentlich entfernen.
  5. 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:

  1. zaehleGruppen(...)
  2. fuelleGruppenArrays(...)
  3. berechneDurchschnittsalter(...)
  4. druckeErgebnis(...)

Diese Uebertragung zeigt, dass Strukturierungsprinzipien nicht auf Statistikzahlen beschraenkt sind.

Code-Review-Checkliste

  1. Hat jede Methode genau eine Hauptaufgabe?
  2. Sind Methodennamen selbsterklaerend?
  3. Werden Randfaelle frueh behandelt?
  4. Sind Berechnung und Ausgabe getrennt?
  5. 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:

  1. Eingabevalidierung separat
  2. Berechnungsteil getrennt
  3. Ausgabe getrennt
  4. keine Duplikate
  5. 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

  1. Woran erkennst du, dass eine Methode zu viele Verantwortungen hat?
  2. Warum sollten Hilfsmethoden meist private sein?
  3. Weshalb ist die Trennung von Berechnung und Ausgabe wichtig?
  4. 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:

  1. Gueltigkeitspruefung isolieren
  2. Hauptberechnung in Teilmethoden zerlegen
  3. Ausgabe/Logging trennen
  4. 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.