📂 Dateien dieser Einheit:
💻 In Web-IDE öffnen → 📄 aufgabe.py (Startercode) 🧪 test_aufgabe.py (Tests) 💡 musterloesung.py (Lösung) 🚀 app.py (App-Start) 📖 README.md

1. 🏆 Dein Meisterstück: Alle 3 Lehrpfade vereint!

Herzlichen Glückwunsch zu diesem Meilenstein! Du hast gelernt, wie man Variablen deklariert, Schleifen baut, Klassen als Baupläne entwirft, Datenstrukturen serialisiert und echte Desktop-Fenster mit Tkinter zum Leben erweckt.

In diesem Master-Abschlussprojekt baust du eine vollwertige, professionelle Software für ein Tierheim: Den PetCare- & Tierheim-Manager. Hier greifen alle Rädchen nahtlos ineinander:

🛣️ Lehrpfad 1: Grundlagen

Typsichere Datenverarbeitung, String-Formatierung für Berichte, Rechnen von Statistiken (Mittelwert, Summen) und sauberer CSV-Export.

🛣️ Lehrpfad 2: OOP & Clean Code

Objekt-Instanziierung, Kapselung, self, __str__, __repr__, 1:n Beziehungen und modulare Methoden.

🛣️ Lehrpfad 3: Professionelle Software

Vererbung (super()), Polymorphie (Tierlaute), eigene Exceptions, JSON-Savegames, Tkinter Desktop-GUI und 100% Unittest-Abdeckung!

2. 🏛️ Die Architektur: Model-View-Controller (MVC)

In professionellen Software-Unternehmen schreibt man niemals Geschäftslogik und Benutzeroberfläche in einen einzigen großen Code-Klotz ("Spaghetti-Code"). Stattdessen trennt man das System strikt nach dem MVC-Muster:

1. Das Model (Daten & Logik)

Klassen Tier & Tierheim

Verwaltet alle Tiere, berechnet Statistiken (Ø Alter, Gewicht), filtert Bestände und speichert/lädt JSON & CSV.

💡 100% Headless testbar: Weiß nichts von Tkinter und läuft komplett ohne Bildschirm!
2. Die View (Anzeige)

Tkinter Widgets

Das visuelle Fenster: Header, Formular-Eingabefelder, Listbox für den Tierbestand, Aktionsbuttons und die dynamische Statusleiste.

👀 Dumb View: Zeigt nur an, was das Model ihr mitteilt.
3. Der Controller (Steuerung)

Klasse TierheimApp

Reagiert auf Benutzerklicks, validiert Eingaben mit try-except, ruft Methoden des Tierheims auf und aktualisiert die Anzeige.

🛡️ Fehler-Abfangjäger: Verhindert App-Abstürze bei Fehleingaben.
🍽️ Die Restaurant-Analogie für MVC:
  • Model (Die Küche): Kocht das Essen, verwaltet die Zutaten und Rezepte (Logik & Daten).
  • View (Die Speisekarte & Teller): Das, was der Gast sieht und liest (Grafik).
  • Controller (Der Kellner): Nimmt die Bestellung vom Gast auf, gibt sie an die Küche weiter und bringt das fertige Gericht an den Tisch!

3. 🧬 Das Datenmodell: Vererbung & Polymorphie

Ein Tierheim beherbergt verschiedene Tierarten: Hunde, Katzen und Vögel. Sie alle teilen gemeinsame Eigenschaften (Name, Alter, Gewicht, Impfstatus, Hunger), besitzen jedoch jeweils eigene Spezialmerkmale und Verhaltensweisen:

Python (Vererbungshierarchie & super())
class Tier:
    def __init__(self, name: str, alter: int, gewicht: float, geimpft: bool = False, hunger: int = 50):
        if not name.strip():
            raise ValidierungsFehler("Name darf nicht leer sein!")
        self.name = name.strip()
        self.alter = alter
        self.gewicht = gewicht
        self.geimpft = geimpft
        self.hunger = max(0, min(100, hunger))

    def mache_laut(self) -> str:
        return f"{self.name} macht ein Geräusch."

class Hund(Tier):
    def __init__(self, name: str, alter: int, gewicht: float, rasse: str = "Mischling", ...):
        super().__init__(name, alter, gewicht, ...)
        self.rasse = rasse
        self.gassigegangen = False

    def mache_laut(self) -> str:
        return f"{self.name} bellt: Wuff! Wuff! 🐶"
🎭 Polymorphie in der Praxis:
Wenn wir im Tierheim for tier in self.tiere: print(tier.mache_laut()) aufrufen, weiß Python dank Polymorphie zur Laufzeit automatisch, welches Tier welchen Laut von sich gibt – ohne eine einzige if/elif-Typabfrage!

4. 💾 Savegame-Persistenz mit dem Factory-Muster

Beim Speichern als JSON-Datei wandeln wir jedes Tier-Objekt in ein Dictionary um und ergänzen den Schlüssel "art": "Hund". Beim Laden liest die Factory-Methode Tier.from_dict(data) diesen Schlüssel aus und erzeugt automatisch die exakte Unterklasse:

Python (Factory-Methode mit Type-Discriminator)
@classmethod
def from_dict(cls, data: dict) -> Tier:
    art = data.get("art", "Tier")
    if art == "Hund":
        return Hund(name=data["name"], alter=data["alter"], gewicht=data["gewicht"], rasse=data.get("rasse", "Mischling"), ...)
    elif art == "Katze":
        return Katze(...)
    elif art == "Vogel":
        return Vogel(...)
    else:
        return Tier(...)

5. ✅ Deine Projekt-Checkliste

Arbeite die folgenden 5 Abschnitte in der Datei aufgabe.py der Reihe nach ab:

  • 1. Eigene Exceptions: TierheimFehler, ValidierungsFehler, TierNichtGefundenFehler, KapazitaetUeberschrittenFehler.
  • 2. Basisklasse Tier: Validierung von Name, Alter, Gewicht im __init__, Methoden fuettern(), impfen(), to_dict() und Factory-Methode from_dict().
  • 3. Kindklassen Hund, Katze, Vogel: Vererbung mit super(), artspezifische Attribute & Methoden (gassi_gehen(), kratzen(), fliegen()) und polymorphes mache_laut().
  • 4. Geschäftslogik Tierheim: Tieraufnahme mit Kapazitätsprüfung, Vermittlung/Entlassen, Filter nach Art/Impfung/Hunger, Statistiken (Ø Alter, Gewicht) und JSON-/CSV-Persistenz.
  • 5. Benutzeroberfläche TierheimApp: Tkinter-Events mit dem Model verknüpfen, try-except Fehlerabfang und dynamische Statusleisten-Meldungen.

6. 💡 Ausklappbare Hilfestellungen & Tipps

🔍 Tipp zu Schritt 1: Eigene Exceptions definieren

Eigene Exception-Klassen erben in Python einfach von Exception oder einer übergeordneten Basis-Exception:

class TierheimFehler(Exception):
    pass

class ValidierungsFehler(TierheimFehler):
    pass
🔍 Tipp zu Schritt 4: CSV-Export mit dem csv-Modul

Nutze csv.writer mit newline="" für saubere Tabellenausgabe:

with open(dateipfad, "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["Art", "Name", "Alter", "Gewicht", "Geimpft", "Hunger", "Details"])
    for t in self.tiere:
        writer.writerow([t.__class__.__name__, t.name, t.alter, f"{t.gewicht:.1f}", "Ja" if t.geimpft else "Nein", f"{t.hunger}%", t.get_details()])
🔍 Tipp zu Schritt 5: Fehler im GUI-Controller sanft abfangen

Damit die Desktop-App bei einer Fehleingabe nicht abstürzt, fange Exceptions im Event-Handler ab:

try:
    self.tierheim.tier_aufnehmen(neues_tier)
    self.aktualisiere_ansicht()
    self.setze_status(f"{neues_tier.name} aufgenommen! 🎉", typ="success")
except TierheimFehler as e:
    self.setze_status(str(e), typ="warning")

7. 🧪 Lösung überprüfen & App starten

1. Automatische Unittests ausführen:

Terminal (im Ordner 16_master_abschlussprojekt)
python3 test_aufgabe.py

2. Grafische Desktop-Applikation starten:

Terminal
python3 app.py

🧠 Diagnostischer Selbst-Check

Überprüfe dein Verständnis der Kernkonzepte und typischen Denkfallen, bevor du den Code in der Web-IDE schreibst.