Kapitel 02: Refactoring

Vom Monolithen zu Modulen

Software Engineering - Wintersemester 2025/26

Eine praktische Anleitung zum Refactoring des Road Profile Viewers von einem 390-Zeilen-Monolithen zu modularem, testbarem Code.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Wo wir jetzt stehen

Herzlichen Glückwunsch! Du hast erreicht:

✅ Kapitel 02 (Code-Qualität in der Praxis): PEP8-Konformität mit Ruff
✅ Kapitel 02 (Feature-Branch-Entwicklung): Feature Branches & Pull Requests
✅ Kapitel 02 (Automatisierung und CI/CD): Automatisierte CI/CD-Checks

Deine CI ist grün! 🎉

Aber... deine gesamte App lebt in einer einzigen 390-Zeilen main.py Datei.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Das Problem: Echte Schmerzpunkte

Szenario 1: Die Bug-Jagd

Du: "Da ist ein Bug in der Schnittpunkt-Berechnung."
Du: *Scrollt durch 390 Zeilen*
Du: *Passiert generate_road_profile(), create_dash_app()...*
Du: "Gefunden bei Zeile 267! Moment, wovon hängt das ab?"

Szenario 2: Der Merge-Konflikt

Student A: Bearbeitet Zeilen 50-120 (Straßengenerierung)
Student B: Bearbeitet Zeilen 200-350 (UI-Styling)
Ergebnis: MERGE-KONFLIKT (trotz unabhängiger Änderungen!)
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Das Problem: Test-Albtraum

Szenario 3: Testen (Vorschau auf Kapitel 03 (Grundlagen des Testens))

# Du willst find_intersection() testen
from main import find_intersection

# Was tatsächlich passiert:
# - Importiert das gesamte Dash-Framework
# - Startet Webserver
# - Dauert 5 Sekunden pro Test
# - 20 Funktionen zu testen = 100 Sekunden!

Ergebnis: Du gibst das Testen auf. 😞

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Heutige Lernziele

Am Ende dieser Vorlesung wirst du:

  1. ✅ Verstehen warum monolithischer Code unwartbar wird
  2. ✅ Identifizieren natürliche Grenzen in deinem Code
  3. ✅ Refactoren einen Monolithen in fokussierte Module
  4. ✅ Organisieren Imports um zirkuläre Abhängigkeiten zu vermeiden
  5. ✅ Erleben die Vorteile von modularem Code
  6. ✅ Vorbereiten deine Codebasis fürs Testen (Kapitel 03 (Grundlagen des Testens))
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Was du heute NICHT lernst

Nicht behandelt (noch nicht):

  • ❌ Design Patterns mit Namen (ergeben sich natürlich aus der Praxis)
  • ❌ Fortgeschrittene Architekturmuster (kommen später)
  • ❌ Testen (das ist Kapitel 03 (Grundlagen des Testens)!)

Heutiger Fokus: Praktisches Refactoring mit echtem Code.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Feature-Development-Workflow anwenden

Erinnerst du dich an den Workflow aus Kapitel 02 (Feature-Entwicklung)?

  1. Erstelle einen Feature-Branch
  2. Implementiere deine Änderungen
  3. Pushe zu GitHub
  4. Öffne einen Pull Request
  1. Automatisierte CI-Checks laufen
  2. Code Review
  3. Merge bei Genehmigung
  4. Lösche den Branch

Heutiges Refactoring IST ein Feature! Wir nutzen diesen Workflow.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Schritt 1: Feature-Branch erstellen

# Stelle sicher, dass du auf main bist und aktuell
$ git checkout main
$ git pull origin main

# Erstelle einen neuen Feature-Branch
$ git checkout -b feature/refactor-to-modules
Switched to a new branch 'feature/refactor-to-modules'

# Überprüfe, dass du auf dem neuen Branch bist
$ git branch
  main
* feature/refactor-to-modules

Warum? Main bleibt stabil während wir sicher experimentieren.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Der Plan: Iteratives Refactoring

Kleine, sichere Schritte mit Commits nach jedem:

Schritt 1: Extrahiere geometry.py → Commit → Test
Schritt 2: Extrahiere road.py → Commit → Test
Schritt 3: Extrahiere visualization.py → Commit → Test
Schritt 4: Vereinfache main.py → Commit → Test
Final: Pushe Branch → Öffne PR → CI validiert → Merge

Schlüsselprinzip: Nach jedem Schritt funktioniert die Anwendung noch perfekt.

Warum kleine Schritte? Leicht zu erkennen was kaputtging, leicht rückgängig zu machen.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Den Monolithen verstehen

Was ist ein Monolith?

Code, wo alles an einem Ort lebt, eng miteinander gekoppelt.

Dein aktuelles main.py (390 Zeilen):

  • Straßenprofil-Generierung (Zeilen 20-60)
  • Geometrie-Berechnungen (Zeilen 60-180)
  • Dash-Anwendungs-UI (Zeilen 190-390)
  • Anwendungs-Einstiegspunkt

Alles ist durcheinander: Mathe, UI, Datengenerierung, App-Logik.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Warum Monolithen zu Problemen werden

1. Schwer zu navigieren

  • Spezifische Funktionalität zu finden erfordert durch unabhängigen Code zu scrollen
  • Zeile 111? War das Geometrie oder Straßengenerierung?

2. Schwer zu testen

  • Muss alles importieren um eine Funktion zu testen
  • Dash startet, langsame Imports, Seiteneffekte

3. Schwer zusammenzuarbeiten

  • Zwei Entwickler bearbeiten dieselbe Datei = Merge-Konflikte
  • Auch wenn die Änderungen völlig unabhängig sind!
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Warum Monolithen zu Problemen werden (2)

4. Hohe Kopplung

def find_intersection(...):
    # Verwendet versehentlich eine globale Variable aus dem UI-Bereich
    camera_x = CAMERA_POSITION  # Wo ist das definiert??
    # Jetzt hängt Geometrie von UI ab - schwer zu testen!

5. Verletzt "Eine Datei, Ein Zweck"

  • Was macht main.py?
  • Aktuelle Antwort: "Alles!"
  • Bessere Antwort: "Startet die Anwendung. Das war's."
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Natürliche Grenzen identifizieren

Der "3-Wörter-Beschreibung"-Test

Wenn du ein Modul in 3 Wörtern oder weniger beschreiben kannst, ist es fokussiert genug.

✅ Gute Beispiele:

  • geometry.py → "Strahlenschnitt-Mathematik"
  • road.py → "Straßenprofil-Generierung"
  • visualization.py → "Dash UI-Komponenten"
  • main.py → "Anwendungs-Einstiegspunkt"
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Der "3-Wörter-Test" (Fortsetzung)

❌ Schlechte Beispiele:

  • utilities.py → "Verschiedene nützliche Sachen" (zu vage!)
  • helpers.py → "Hilfsfunktionen" (welche Art??)
  • functions.py → "Verschiedene Funktionen" (bedeutungslos!)

Schlüsselprinzip: Spezifische, fokussierte Benennung zeigt klaren Zweck.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Deinen aktuellen Code analysieren

Kategorie 1: Reine Mathe-Funktionen

  • calculate_ray_line() - Hängt nur von numpy ab
  • find_intersection() - Hängt nur von numpy ab
  • Charakteristik: Gleiche Eingaben = gleiche Ausgaben (rein)
  • Ziel: geometry.py

Kategorie 2: Datengenerierung

  • generate_road_profile() - Hängt nur von numpy ab
  • Charakteristik: Generiert Daten, zeigt sie aber nicht an
  • Ziel: road.py
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Deinen aktuellen Code analysieren (2)

Kategorie 3: UI und Anwendungslogik

  • create_dash_app() - Hängt von Dash, Geometrie, Road ab
  • update_graph() Callback - Orchestriert alles
  • Charakteristik: Erstellt UI, behandelt Benutzereingaben
  • Ziel: visualization.py

Kategorie 4: Einstiegspunkt

  • main() - Startet nur die Anwendung
  • Charakteristik: Minimale Logik
  • Ziel: main.py (einfach halten!)
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Die Abhängigkeits-Hierarchie

Natürlicher Abhängigkeitsfluss:

main.py
    ↓ abhängig von
visualization.py
    ↓ abhängig von
geometry.py, road.py
    ↓ abhängig von
numpy (externe Bibliothek)

Schlüssel-Einsicht: Abhängigkeiten fließen NUR IN EINE RICHTUNG.

Warum? Verhindert zirkuläre Abhängigkeiten!

✅ visualization.py kann aus geometry.py importieren

❌ geometry.py sollte NICHT aus visualization.py importieren

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Zielstruktur

Nach dem Refactoring:

road-profile-viewer/
├── main.py                 # Nur Einstiegspunkt (~15 Zeilen)
├── geometry.py            # Reine Mathe-Funktionen (~80 Zeilen)
├── road.py                # Straßengenerierung (~60 Zeilen)
├── visualization.py       # Dash-App und UI (~200 Zeilen)
└── (andere Dateien bleiben gleich)

Von 1 Datei (390 Zeilen) → 4 fokussierte Module (465 Zeilen gesamt)

Zusätzliche Zeilen sind Dokumentation - das ist gut! 📝

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 1 - Modul-Dateien erstellen

# In deinem road-profile-viewer-Verzeichnis
$ touch geometry.py
$ touch road.py
$ touch visualization.py

# Überprüfe die Struktur
$ ls *.py
geometry.py  main.py  road.py  visualization.py

Jetzt haben wir unsere Modul-Dateien bereit!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 2 - Geometrie extrahieren

Erstelle geometry.py mit:

  • calculate_ray_line() Funktion
  • find_intersection() Funktion
  • Umfassende Docstrings
  • Type Hints für IDE-Unterstützung

Aktualisiere main.py:

from geometry import calculate_ray_line, find_intersection

Lösche die Geometrie-Funktionsdefinitionen aus main.py.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 2 - Testen & Committen

Teste, dass es funktioniert:

$ uv run road-profile-viewer
# Anwendung sollte normal starten
# Überprüfe, dass Strahlenschnitt noch funktioniert

✅ Checkpoint: Anwendung funktioniert!

Committe deinen Fortschritt:

$ git add geometry.py main.py
$ git commit -m "Extract geometry functions to geometry.py

- Move calculate_ray_line() and find_intersection()
- Add comprehensive docstrings and type hints
- Update main.py imports
- Application still works identically"
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 3 - Road extrahieren

Erstelle road.py mit:

  • generate_road_profile() Funktion
  • Docstrings, die die Klothoiden-Approximation erklären

Aktualisiere main.py:

from road import generate_road_profile

Lösche die Straßengenerierungs-Funktion aus main.py.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 3 - Testen & Committen

Teste erneut:

$ uv run road-profile-viewer
# Überprüfe, dass Straßengenerierung noch funktioniert

✅ Checkpoint: Funktioniert noch!

Committe diesen Schritt:

$ git add road.py main.py
$ git commit -m "Extract road generation to road.py

- Move generate_road_profile()
- Add docstrings
- Update imports
- Application still works identically"
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 4 - Visualization extrahieren

Erstelle visualization.py mit:

  • create_dash_app() Funktion
  • Allem UI-Layout-Code
  • Allen Callbacks
  • Imports aus geometry und road Modulen

Vereinfache main.py:

from visualization import create_dash_app

def main():
    app = create_dash_app()
    print("Starting Road Profile Viewer...")
    app.run(debug=True)
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 4 - Testen & Committen

Teste das komplette Refactoring:

$ uv run road-profile-viewer
# Überprüfe dass ALLES noch funktioniert:
# - Straße wird korrekt gerendert
# - Strahlwinkel passt sich an
# - Schnittpunkt aktualisiert sich
# - Distanz wird angezeigt

✅ Checkpoint: Alles funktioniert! 🎉

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Praktisch: Schritt 4 - Finaler Commit

$ git add visualization.py main.py
$ git commit -m "Extract UI layer to visualization.py

- Move create_dash_app() and all UI code
- Simplify main.py to just entry point (~20 lines)
- visualization.py imports from geometry and road
- Application works identically to before

Completes modular refactoring:
main → visualization → geometry/road"

Jetzt haben wir eine saubere Commit-Historie, die die Refactoring-Progression zeigt!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Das Refactoring überprüfen

Überprüfe deine Modul-Struktur:

$ ls *.py
geometry.py  main.py  road.py  visualization.py

Überprüfe Zeilenzahlen:

$ wc -l *.py
   175 geometry.py     # Reine Geometrie-Berechnungen
    67 road.py         # Straßengenerierung
   203 visualization.py # Aller UI-Code
    20 main.py         # Nur der Einstiegspunkt
   ---

<!-- _header: '<div class="header-info"><span>Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen</span><span></span></div><div class="header-logo" role="img" aria-label="Hochschule Aalen"></div>' -->

   465 total

main.py ging von 390 Zeilen auf 20 Zeilen! 📉

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Abhängigkeitsfluss überprüfen

# main.py importiert:
from visualization import create_dash_app

# visualization.py importiert:
from geometry import calculate_ray_line, find_intersection
from road import generate_road_profile

# geometry.py importiert:
import numpy as np  # Nur externe Abhängigkeit

# road.py importiert:
import numpy as np  # Nur externe Abhängigkeit

✅ Einseitige Abhängigkeiten - keine Zyklen!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gewonnene Vorteile: Einfache Navigation

Vorher:

# "Wo ist die Schnittpunkt-Berechnung?"
# *Scrollt durch 390 Zeilen*
# *Verirrt sich in unabhängigem Code*

Nachher:

# "Wo ist die Schnittpunkt-Berechnung?"
# Öffnet geometry.py → find_intersection() ist direkt da!

Gewinn: Code in Sekunden statt Minuten finden.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gewonnene Vorteile: Fokussierte Änderungen

Vorher:

# Änderung des Straßengenerierungs-Algorithmus
# Datei: main.py (390 Zeilen)
# Risiko: Könnte versehentlich UI-Code kaputt machen

Nachher:

# Änderung des Straßengenerierungs-Algorithmus
# Datei: road.py (67 Zeilen)
# Sicherheit: Kann UI-Code nicht versehentlich anfassen!

Gewinn: Änderungen sind sicherer und fokussierter.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gewonnene Vorteile: Bessere Zusammenarbeit

Vorher:

Student A: Bearbeitet main.py Zeilen 50-120 (Straßengenerierung)
Student B: Bearbeitet main.py Zeilen 200-350 (UI-Styling)
Ergebnis: MERGE-KONFLIKT! 😡
Zeitverschwendung: 30 Minuten Konflikte auflösen

Nachher:

Student A: Bearbeitet road.py
Student B: Bearbeitet visualization.py
Ergebnis: Keine Konflikte! 😊
Zeitverschwendung: 0 Minuten

Gewinn: Parallele Entwicklung ohne Konflikte!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gewonnene Vorteile: Testbarkeit

Vorher:

# Um find_intersection() zu testen
from main import find_intersection
# Importiert ALLES (Dash, UI, etc.)
# Langsam, schwer, Seiteneffekte

Nachher:

# Um find_intersection() zu testen
from geometry import find_intersection
# Importiert nur Geometrie-Modul
# Schnell, leichtgewichtig, keine Seiteneffekte

Gewinn: Schnelle, fokussierte Tests (Kapitel 03 (Grundlagen des Testens)!)

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gewonnene Vorteile: Wiederverwendbarkeit

Vorher:

# Willst du find_intersection() in einem anderen Projekt nutzen?
# Copy-Paste aus main.py
# → Bringt unnötigen Dash-Code mit 😞

Nachher:

# Willst du find_intersection() in einem anderen Projekt nutzen?
# Kopiere einfach geometry.py
# → Sauberes, eigenständiges Modul! 😊

Gewinn: Reine Funktionen sind überall wiederverwendbar.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Häufiger Fallstrick #1: Zirkuläre Imports

Der Fehler:

ImportError: cannot import name 'generate_road_profile'
from partially initialized module 'road'
(most likely due to a circular import)

Die Ursache:

# visualization.py
from road import generate_road_profile

# road.py (SCHLECHT!)
from visualization import create_dash_app
# Warum sollte road.py UI-Code brauchen??
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Häufiger Fallstrick #1: Lösung

Die Lösung:

Regel: Module niedrigerer Ebene (geometry, road) sollten NIEMALS aus Modulen höherer Ebene (visualization, main) importieren.

Abhängigkeiten fließen in eine Richtung:

main → visualization → geometry/road

Nicht:

geometry ← visualization ← main (❌ FALSCH!)
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Häufiger Fallstrick #2: Unklare Grenzen

Die Verwirrung:

# Wo gehören camera_x und camera_y hin?
# - geometry.py? (werden in Berechnungen verwendet)
# - visualization.py? (ist ein UI-Parameter)
# - Eine neue config.py Datei?

Die Lösung:

  • Wenn hardcodiert: Behalte als Parameter-Default in Funktionssignatur
  • Wenn vom Benutzer konfigurierbar: Behalte in visualization.py (UI entscheidet)
  • Erstelle "config.py" nicht vorzeitig! Du wirst wissen, wann es gebraucht wird.
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Häufiger Fallstrick #3: Über-Refactoring

Die Versuchung:

Sollte ich erstellen:
- geometry_helpers.py?
- geometry_utils.py?
- ray_calculations.py?
- intersection_math.py?
- angle_converter.py?

Die Lösung: YAGNI-Prinzip

  • "You Ain't Gonna Need It" (Du wirst es nicht brauchen)
  • Beginne mit 3-4 fokussierten Modulen
  • Teile nur, wenn Modul zu groß wird (>300 Zeilen)
  • Vermeide "utility/helper"-Module - sie werden zu Müllkippen!
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Häufiger Fallstrick #4: Imports vergessen

Der Fehler:

# In main.py
def main():
    x, y = generate_road_profile()
# NameError: name 'generate_road_profile' is not defined

Die Lösung:

# Füge den Import am Anfang hinzu
from road import generate_road_profile

Pro-Tipp: Nutze IDE Auto-Import (Ctrl+. in VS Code).

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

CI-Checks ausführen

Dein Refactoring sollte alle CI-Checks bestehen:

# Führe Ruff aus (Style-Check)
$ uv run ruff check .
All checks passed! ✅

# Führe Ruff Format-Check aus
$ uv run ruff format --check .
All files formatted correctly! ✅

# Führe Pyright aus (Type-Check)
$ uv run pyright
0 errors, 0 warnings ✅

Wenn du Fehler bekommst: Behebe sie vor dem Pushen!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Deinen Feature-Branch pushen

Überprüfe deine Commits:

$ git log --oneline
7h8i9j0 Extract UI layer to visualization.py
d4e5f6g Extract road generation to road.py
a1b2c3d Extract geometry functions to geometry.py

Saubere, logische Progression! ✨

Pushe zu GitHub:

$ git push -u origin feature/refactor-to-modules
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Pull Request erstellen

$ gh pr create \
  --title "Refactor: Split monolithic main.py into focused modules" \
  --body "Refactors monolithic main.py (390 lines) into 4 modules:

- geometry.py: Pure math functions
- road.py: Road generation logic
- visualization.py: Dash UI layer
- main.py: Entry point only (20 lines)

Benefits: Easier navigation, testing, reduced merge conflicts

✅ All Ruff/Pyright checks pass
✅ Application works identically"

Oder nutze das GitHub Web-Interface!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Auf CI-Checks warten

GitHub Actions wird automatisch laufen:

✅ Ruff check (style)
✅ Ruff format check
✅ Pyright (types)

Alle sollten bestehen! (Du hast sie lokal ausgeführt.)

Sobald grün: Bereit zum Mergen! 🚀

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

KI-Coding-Assistenten nutzen

Wichtiger Hinweis:

Bevor du KI für Refactoring verwendest, MUSST du verstehen:

  • ✅ Was gute Modul-Grenzen ausmacht
  • ✅ Wie man zirkuläre Abhängigkeiten vermeidet
  • ✅ Der "3-Wörter-Beschreibung"-Test
  • ✅ Einseitiger Abhängigkeitsfluss

Warum? Ohne diese Prinzipien kannst du nicht:

  • Effektive Prompts schreiben
  • Vorschläge der KI bewerten
  • Subtile Fehler erkennen

KI ist ein Werkzeug, kein Ersatz für dein Wissen!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Was KI kann und was nicht

KI kann helfen bei:

  • ✅ Mechanischer Code-Verschiebung (copy/paste zwischen Dateien)
  • ✅ Import-Anweisungen aktualisieren
  • ✅ Boilerplate schreiben (Docstrings, Type Hints)
  • ✅ Konsistenz wahren

KI kann nicht:

  • ❌ Entscheiden WO Code geteilt wird (erfordert Urteilsvermögen)
  • ❌ Architektur-Bedürfnisse deines Projekts verstehen
  • ❌ Abwägungen bewerten
  • ❌ Übereinstimmung mit Team-Konventionen sicherstellen
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

KI-Prompt

Du hast das Refactoring geplant (manuell!), jetzt hilft KI bei der Ausführung.

Du wirst die monolithische main.py (390 Zeilen) refactoren in:
- geometry.py - Reine Mathe-Funktionen
- road.py - Straßenprofil-Generierung
- visualization.py - Dash UI-Schicht
- main.py - Einstiegspunkt (~20 Zeilen)

Erstelle Feature-Branch feature/refactor-to-modules
Mache 4 inkrementelle Commits (einen pro Schritt).

Schritt 1: Geometrie-Modul extrahieren
- Kopiere calculate_ray_line() und find_intersection()
- Füge Imports hinzu: import numpy as np
- Behalte alle Docstrings und Type Hints
- Commit: "refactor: extract geometry to separate module"

[Weiter mit Schritten 2, 3, 4...]
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Warum dieser Prompt funktioniert

Klare Struktur:

  • ✅ Explizite Dateinamen und Speicherorte
  • ✅ Schritt-für-Schritt-Aufschlüsselung
  • ✅ Spezifische Anforderungen
  • ✅ Commit-Message-Format

Enthält Kontext:

  • ✅ Erklärt WARUM (absolute Imports, etc.)
  • ✅ Was bewahrt werden soll (Docstrings)
  • ✅ Zeigt gewünschten Endzustand

Ermöglicht Verifikation:

  • ✅ Jeder Schritt unabhängig testbar
  • ✅ Klare Erfolgskriterien
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Deine Verantwortung nach der Code-Generierung

Akzeptiere niemals blind von KI generierten Code!

Immer:

  1. ✅ Jede Zeile lesen - Verstehen was sich änderte
  2. ✅ Nach jedem Schritt testen - uv run road-profile-viewer
  3. ✅ Imports überprüfen - Auf zirkuläre Abhängigkeiten prüfen
  4. ✅ CI-Checks ausführen - Sicherstellen Ruff, Pyright bestehen
  5. ✅ Commits überprüfen - git diff kontrollieren
  6. ✅ Struktur validieren - Entspricht es deinem Plan?
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Warnzeichen beachten

Häufige KI-Fehler:

  • ❌ Zirkuläre Imports (geometry importiert aus visualization)
  • ❌ Fehlende oder falsche Import-Pfade
  • ❌ Verlorene Funktionalität (gelöscht statt verschoben)
  • ❌ Geänderte Logik (KI hat unnötig "verbessert")
  • ❌ Inkonsistente Benennung oder Stil

Du bist die Qualitätskontrolle!

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Das Mensch-KI-Kollaborationsmodell

Mensch: Strategisches Denken
├── Monolith-Probleme identifizieren
├── Modul-Grenzen entscheiden
├── Abhängigkeitshierarchie planen
└── Erfolgskriterien definieren
        ↓
KI: Taktische Ausführung
├── Code zwischen Dateien verschieben
├── Boilerplate-Code schreiben
└── Commit-Messages formatieren
        ↓
Mensch: Verifikation & Qualität
├── Funktionalität testen
├── Architektur überprüfen
├── Nach subtilen Bugs suchen
└── Gegen CI validieren

Du bist der Architekt. KI ist die Baufirma.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Lernübungs-Empfehlung

Für Studenten:

1. Erstes Mal: Manuell durchführen (heutige Übung)

  • Herausforderungen tiefgreifend verstehen
  • Intuition für Probleme aufbauen
  • Lernen, zirkuläre Abhängigkeiten zu erkennen

2. Zweites Mal: KI-Unterstützung nutzen (zukünftige Projekte)

  • Jetzt kannst du KI-Vorschläge bewerten
  • Du wirst ihre Fehler erkennen
  • Du wirst bessere Prompts schreiben

Warum diese Reihenfolge? Du kannst ein Werkzeug nicht effektiv nutzen, das du nicht verstehst.

Lerne zuerst Prinzipien, dann nutze Automatisierung.

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Zusammenfassung: Vorher vs. Nachher

Vor dem Refactoring:

main.py (390 Zeilen)
└── Alles durcheinander: Mathe, UI, Daten, Startup
  • ❌ Schwer Code zu finden
  • ❌ Schwer zu testen
  • ❌ Merge-Konflikte
  • ❌ Enge Kopplung

Nach dem Refactoring:

├── geometry.py (175 Zeilen)
├── road.py (67 Zeilen)
├── visualization.py (203 Zeilen)
└── main.py (20 Zeilen)
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Zusammenfassung: Vorteile

✅ Einfache Navigation - Klare Modul-Namen
✅ Testbar - Geometrie ohne Dash importieren
✅ Kollaborativ - Verschiedene Dateien gleichzeitig bearbeiten
✅ Wiederverwendbar - Reine Funktionen in eigenständigen Modulen
✅ Wartbar - Module mit einzelner Verantwortung

Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Gelernte Schlüsselprinzipien

  1. Separation of Concerns (Trennung der Zuständigkeiten)

    • Jedes Modul macht eine Sache gut
  2. Abhängigkeits-Richtung

    • Module niedrigerer Ebene importieren nicht aus höherer Ebene
  3. Der "3-Wörter-Beschreibung"-Test

    • Kannst du das Modul prägnant beschreiben?
  4. YAGNI ("You Ain't Gonna Need It")

    • Erstelle keine Abstraktionen bis sie gebraucht werden
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Wichtige Erkenntnisse

Erinnere dich:

  1. Monolithen wachsen organisch - Anfangs in Ordnung, später Probleme
  2. Refactoring ≠ Neuschreiben - Gleiche Funktionalität, bessere Struktur
  3. Module brauchen klare Grenzen - Reine Funktionen vs. UI
  4. Abhängigkeiten fließen in eine Richtung - Verhindert zirkuläre Imports
  5. Testbarkeit ergibt sich aus Modularität - Kann nicht testen was man nicht importieren kann
  6. Der "3-Wörter-Test" - Beschreibe Modul-Zweck prägnant
  7. YAGNI - Beginne einfach, refactore wenn nötig
  8. CI sollte bestehen - Refactoring ändert nicht die Funktionalität
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

Weiterführende Literatur

Über Refactoring:

  • Martin Fowler's "Refactoring: Improving the Design of Existing Code"
  • Zitat: "Jeder Dummkopf kann Code schreiben, den ein Computer versteht. Gute Programmierer schreiben Code, den Menschen verstehen."

Über Modul-Design:

  • Robert C. Martin's "Clean Code"
  • SOLID-Prinzipien (du wendest Single Responsibility an!)

Über Python-Module:

  • Real Python: Python Modules and Packages
  • PEP 8: Package and Module Names
Software Engineering | WiSe 2025 | Refactoring: Monolith zu Modulen

🎯 Übungszeit: Praktische Aufgabe!

Jetzt bist du dran, das Gelernte anzuwenden!

Was du tun wirst:

  • ✅ Eine echte monolithische Codebasis refactoren (390 Zeilen → 4 Module)
  • ✅ Die genauen Schritte aus der heutigen Vorlesung befolgen
  • ✅ Automatisiertes Feedback zu deinem Refactoring erhalten
  • ✅ Deine Punktzahl steigen sehen bei jedem abgeschlossenen Schritt

Aufgabe annehmen:
👉 https://classroom.github.com/a/swPrBybO

Erlebe den vollständigen Workflow: Feature-Branch → Commits → Tests → CI/CD