Aufgaben-Python/lehrpfad_3_fortgeschrittenes_oop/16_master_abschlussprojekt/index.html

476 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kapitel 16: Master-Abschlussprojekt – PetCare & Tierheim-Manager</title>
<link rel="stylesheet" href="../../assets/style.css">
</head>
<body>
<div class="app-layout">
<aside class="app-sidebar">
<div class="sidebar-header">
<a href="../../index.html" class="sidebar-brand-link">
<div class="sidebar-logo">🐍</div>
<div>
<div class="sidebar-title">Python Portal</div>
<div class="sidebar-subtitle">Lernplattform</div>
</div>
</a>
</div>
<div class="sidebar-quick-nav">
<a href="../../index.html" class="sidebar-link">🏠 Startseite</a>
<a href="../../index.html#tutorial" class="sidebar-link">📖 Tutorial &amp; Workflow</a>
<a href="../../index.html#zertifikate" class="sidebar-link">🏆 Zertifikate</a>
</div>
<div class="sidebar-nav">
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🌱 1. Grundlagen</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">G01–G10</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_1_grundlagen/01_erste_schritte_taschenrechner/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧮</span>
<span class="sidebar-link-text">G01. Taschenrechner</span>
</a>
<a href="../../lehrpfad_1_grundlagen/02_variablen_und_datentypen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">📦</span>
<span class="sidebar-link-text">G02. Variablen & Typen</span>
</a>
<a href="../../lehrpfad_1_grundlagen/03_ein_und_ausgabe/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💬</span>
<span class="sidebar-link-text">G03. Ein- & Ausgabe</span>
</a>
<a href="../../lehrpfad_1_grundlagen/04_verzweigungen_und_bedingungen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🚦</span>
<span class="sidebar-link-text">G04. Bedingungen (if)</span>
</a>
<a href="../../lehrpfad_1_grundlagen/05_schleifen_und_wiederholungen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎡</span>
<span class="sidebar-link-text">G05. Schleifen (for/while)</span>
</a>
<a href="../../lehrpfad_1_grundlagen/06_funktionen_und_module/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🪄</span>
<span class="sidebar-link-text">G06. Funktionen & Module</span>
</a>
<a href="../../lehrpfad_1_grundlagen/07_listen_und_sequenzen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">📋</span>
<span class="sidebar-link-text">G07. Listen & Sequenzen</span>
</a>
<a href="../../lehrpfad_1_grundlagen/08_textverarbeitung_und_strings/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🔤</span>
<span class="sidebar-link-text">G08. String-Methoden</span>
</a>
<a href="../../lehrpfad_1_grundlagen/09_dictionaries_und_sets/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🗃️</span>
<span class="sidebar-link-text">G09. Dicts & Sets</span>
</a>
<a href="../../lehrpfad_1_grundlagen/10_comprehensions_datum_algorithmen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🚀</span>
<span class="sidebar-link-text">G10. Comprehensions</span>
</a>
</div>
</div>
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🏗️ 2. OOP Einstieg</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">00–06</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_2_oop_einstieg/00_fehlersuche_und_grundlagen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🔍</span>
<span class="sidebar-link-text">00. Fehlersuche & Debug</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/01_einstieg_klassen/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🏗️</span>
<span class="sidebar-link-text">01. Einstieg in Klassen</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/02_init_und_self/index.html" class="sidebar-link">
<span class="sidebar-link-icon">⚙️</span>
<span class="sidebar-link-text">02. Konstruktor & self</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/03_methoden_und_verhalten/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🏎️</span>
<span class="sidebar-link-text">03. Methoden & Verhalten</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04_str_und_darstellung/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧾</span>
<span class="sidebar-link-text">04. __str__ Darstellung</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04b_umstieg_vscode/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💻</span>
<span class="sidebar-link-text">04b. VS Code Setup</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/04c_git_und_versionskontrolle/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🌿</span>
<span class="sidebar-link-text">04c. Git-Versionskontrolle</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/05_objekte_kombinieren/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎵</span>
<span class="sidebar-link-text">05. Objekte kombinieren</span>
</a>
<a href="../../lehrpfad_2_oop_einstieg/06_abschlussprojekt_tamagotchi/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🥚</span>
<span class="sidebar-link-text">06. Projekt: Tamagotchi</span>
</a>
</div>
</div>
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>🚀 3. Fortgeschritten</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">07–16</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px;">
<a href="../../lehrpfad_3_fortgeschrittenes_oop/07_referenzen_und_speicher/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧠</span>
<span class="sidebar-link-text">07. Referenzen & Speicher</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/08_operator_overloading_dunder/index.html" class="sidebar-link">
<span class="sidebar-link-icon">➕</span>
<span class="sidebar-link-text">08. Operator Overloading</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/09_eigene_unit_tests_schreiben/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧪</span>
<span class="sidebar-link-text">09. Unit Tests & TDD</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/10_vererbung_und_super/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🧬</span>
<span class="sidebar-link-text">10. Vererbung & super()</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/11_polymorphie_und_interfaces/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎭</span>
<span class="sidebar-link-text">11. Polymorphie</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/12_exceptions_und_fehlerbehandlung/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🛡️</span>
<span class="sidebar-link-text">12. Exceptions & Fehler</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/13_persistenz_json_und_csv/index.html" class="sidebar-link">
<span class="sidebar-link-icon">💾</span>
<span class="sidebar-link-text">13. Persistenz (JSON/CSV)</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/14_gui_mit_tkinter/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🖥️</span>
<span class="sidebar-link-text">14. Desktop-GUIs (Tkinter)</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/15_parameter_und_container/index.html" class="sidebar-link">
<span class="sidebar-link-icon">🎒</span>
<span class="sidebar-link-text">15. Container & *args</span>
</a>
<a href="../../lehrpfad_3_fortgeschrittenes_oop/16_master_abschlussprojekt/index.html" class="sidebar-link active">
<span class="sidebar-link-icon">🏆</span>
<span class="sidebar-link-text">16. Master-Abschlussprojekt</span>
</a>
</div>
</div>
</div>
<div class="sidebar-footer">
<div style="display: flex; align-items: center; justify-content: space-between;">
<div style="font-size: 0.85rem; font-weight: 700; color: white;" id="sidebar-level-text">⭐ Level 1</div>
<div style="font-size: 0.82rem; font-weight: 700; color: #38bdf8;" id="sidebar-xp-text">0 XP</div>
</div>
</div>
</aside>
<div class="app-main">
<main class="container">
<!-- 📂 Schnellzugriff & Download aller Dateien dieser Einheit -->
<div style="background: #ffffff; border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 14px 20px; margin-bottom: 25px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; box-shadow: var(--shadow-sm);">
<div style="font-weight: 700; color: var(--text-main); display: flex; align-items: center; gap: 8px;">
<span>📂 Dateien dieser Einheit:</span>
</div>
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<a href="../../workspace.html?course=python&track=lehrpfad_3_fortgeschrittenes_oop&chapter=16_master_abschlussprojekt" class="btn" style="background: #10b981; color: #fff; font-weight: 700;">💻 In Web-IDE öffnen &rarr;</a>
<a href="aufgabe.py" class="btn" style="padding: 6px 14px; font-size: 0.88rem; background: var(--primary);" download>📄 aufgabe.py (Startercode)</a>
<a href="test_aufgabe.py" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;" download>🧪 test_aufgabe.py (Tests)</a>
<a href="musterloesung.py" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;" download>💡 musterloesung.py (Lösung)</a>
<a href="app.py" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;" download>🚀 app.py (App-Start)</a>
<a href="README.md" class="btn btn-secondary" style="padding: 6px 14px; font-size: 0.88rem;">📖 README.md</a>
</div>
</div>
<!-- 1. Motivierendes Intro & Lehrpfad-Konsolidierung -->
<section class="card">
<h2>1. 🏆 Dein Meisterstück: Alle 3 Lehrpfade vereint!</h2>
<p>
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.
</p>
<p>
In diesem <strong>Master-Abschlussprojekt</strong> baust du eine vollwertige, professionelle Software für ein Tierheim: Den <strong>PetCare- &amp; Tierheim-Manager</strong>. Hier greifen alle Rädchen nahtlos ineinander:
</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 15px; margin: 20px 0;">
<div style="background: #f0fdf4; border-left: 4px solid #10b981; padding: 14px; border-radius: var(--radius-sm);">
<h4 style="color: #166534; margin-bottom: 6px;">🛣️ Lehrpfad 1: Grundlagen</h4>
<p style="font-size: 0.88rem; color: var(--text-muted); margin: 0;">
Typsichere Datenverarbeitung, String-Formatierung für Berichte, Rechnen von Statistiken (Mittelwert, Summen) und sauberer CSV-Export.
</p>
</div>
<div style="background: #eff6ff; border-left: 4px solid #3b82f6; padding: 14px; border-radius: var(--radius-sm);">
<h4 style="color: #1e40af; margin-bottom: 6px;">🛣️ Lehrpfad 2: OOP &amp; Clean Code</h4>
<p style="font-size: 0.88rem; color: var(--text-muted); margin: 0;">
Objekt-Instanziierung, Kapselung, <code>self</code>, <code>__str__</code>, <code>__repr__</code>, 1:n Beziehungen und modulare Methoden.
</p>
</div>
<div style="background: #f5f3ff; border-left: 4px solid #8b5cf6; padding: 14px; border-radius: var(--radius-sm);">
<h4 style="color: #5b21b6; margin-bottom: 6px;">🛣️ Lehrpfad 3: Professionelle Software</h4>
<p style="font-size: 0.88rem; color: var(--text-muted); margin: 0;">
Vererbung (<code>super()</code>), Polymorphie (Tierlaute), eigene Exceptions, JSON-Savegames, Tkinter Desktop-GUI und 100% Unittest-Abdeckung!
</p>
</div>
</div>
</section>
<!-- 2. MVC Architektur -->
<section class="card">
<h2>2. 🏛️ Die Architektur: Model-View-Controller (MVC)</h2>
<p>
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 <strong>MVC-Muster</strong>:
</p>
<div class="mvc-grid">
<div class="mvc-card model">
<span class="badge-master" style="background: #10b981;">1. Das Model (Daten &amp; Logik)</span>
<h3 style="margin-top: 10px; color: #065f46;">Klassen <code>Tier</code> &amp; <code>Tierheim</code></h3>
<p style="font-size: 0.9rem;">
Verwaltet alle Tiere, berechnet Statistiken (Ø Alter, Gewicht), filtert Bestände und speichert/lädt JSON &amp; CSV.
</p>
<div class="box box-tipp" style="margin-top: 10px; font-size: 0.82rem; padding: 8px;">
💡 <strong>100% Headless testbar:</strong> Weiß nichts von Tkinter und läuft komplett ohne Bildschirm!
</div>
</div>
<div class="mvc-card view">
<span class="badge-master" style="background: #3b82f6;">2. Die View (Anzeige)</span>
<h3 style="margin-top: 10px; color: #1e40af;">Tkinter Widgets</h3>
<p style="font-size: 0.9rem;">
Das visuelle Fenster: Header, Formular-Eingabefelder, Listbox für den Tierbestand, Aktionsbuttons und die dynamische Statusleiste.
</p>
<div class="box box-tipp" style="margin-top: 10px; font-size: 0.82rem; padding: 8px;">
👀 <strong>Dumb View:</strong> Zeigt nur an, was das Model ihr mitteilt.
</div>
</div>
<div class="mvc-card controller">
<span class="badge-master" style="background: #8b5cf6;">3. Der Controller (Steuerung)</span>
<h3 style="margin-top: 10px; color: #5b21b6;">Klasse <code>TierheimApp</code></h3>
<p style="font-size: 0.9rem;">
Reagiert auf Benutzerklicks, validiert Eingaben mit <code>try-except</code>, ruft Methoden des Tierheims auf und aktualisiert die Anzeige.
</p>
<div class="box box-tipp" style="margin-top: 10px; font-size: 0.82rem; padding: 8px;">
🛡️ <strong>Fehler-Abfangjäger:</strong> Verhindert App-Abstürze bei Fehleingaben.
</div>
</div>
</div>
<div class="box box-analogie">
<div class="box-title">🍽️ Die Restaurant-Analogie für MVC:</div>
<ul>
<li><strong>Model (Die Küche):</strong> Kocht das Essen, verwaltet die Zutaten und Rezepte (Logik &amp; Daten).</li>
<li><strong>View (Die Speisekarte &amp; Teller):</strong> Das, was der Gast sieht und liest (Grafik).</li>
<li><strong>Controller (Der Kellner):</strong> Nimmt die Bestellung vom Gast auf, gibt sie an die Küche weiter und bringt das fertige Gericht an den Tisch!</li>
</ul>
</div>
</section>
<!-- 3. Klassendiagramm & Vererbung -->
<section class="card">
<h2>3. 🧬 Das Datenmodell: Vererbung &amp; Polymorphie</h2>
<p>
Ein Tierheim beherbergt verschiedene Tierarten: <strong>Hunde</strong>, <strong>Katzen</strong> und <strong>Vögel</strong>.
Sie alle teilen gemeinsame Eigenschaften (Name, Alter, Gewicht, Impfstatus, Hunger), besitzen jedoch jeweils eigene Spezialmerkmale und Verhaltensweisen:
</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Vererbungshierarchie &amp; super())</span>
</div>
<pre><span class="kw">class</span> <span class="cls">Tier</span>:
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>: <span class="cls">str</span>, <span class="var">alter</span>: <span class="cls">int</span>, <span class="var">gewicht</span>: <span class="cls">float</span>, <span class="var">geimpft</span>: <span class="cls">bool</span> = <span class="kw">False</span>, <span class="var">hunger</span>: <span class="cls">int</span> = <span class="num">50</span>):
<span class="kw">if</span> <span class="kw">not</span> <span class="var">name</span>.<span class="fn">strip</span>():
<span class="kw">raise</span> <span class="cls">ValidierungsFehler</span>(<span class="str">"Name darf nicht leer sein!"</span>)
<span class="var">self</span>.<span class="attr">name</span> = <span class="var">name</span>.<span class="fn">strip</span>()
<span class="var">self</span>.<span class="attr">alter</span> = <span class="var">alter</span>
<span class="var">self</span>.<span class="attr">gewicht</span> = <span class="var">gewicht</span>
<span class="var">self</span>.<span class="attr">geimpft</span> = <span class="var">geimpft</span>
<span class="var">self</span>.<span class="attr">hunger</span> = <span class="fn">max</span>(<span class="num">0</span>, <span class="fn">min</span>(<span class="num">100</span>, <span class="var">hunger</span>))
<span class="kw">def</span> <span class="fn">mache_laut</span>(<span class="var">self</span>) -> <span class="cls">str</span>:
<span class="kw">return</span> <span class="str">f"{self.name} macht ein Geräusch."</span>
<span class="kw">class</span> <span class="cls">Hund</span>(<span class="cls">Tier</span>):
<span class="kw">def</span> <span class="fn">__init__</span>(<span class="var">self</span>, <span class="var">name</span>: <span class="cls">str</span>, <span class="var">alter</span>: <span class="cls">int</span>, <span class="var">gewicht</span>: <span class="cls">float</span>, <span class="var">rasse</span>: <span class="cls">str</span> = <span class="str">"Mischling"</span>, ...):
<span class="fn">super</span>().<span class="fn">__init__</span>(<span class="var">name</span>, <span class="var">alter</span>, <span class="var">gewicht</span>, ...)
<span class="var">self</span>.<span class="attr">rasse</span> = <span class="var">rasse</span>
<span class="var">self</span>.<span class="attr">gassigegangen</span> = <span class="kw">False</span>
<span class="kw">def</span> <span class="fn">mache_laut</span>(<span class="var">self</span>) -> <span class="cls">str</span>:
<span class="kw">return</span> <span class="str">f"{self.name} bellt: Wuff! Wuff! 🐶"</span></pre>
</div>
<div class="box box-merke">
<div class="box-title">🎭 Polymorphie in der Praxis:</div>
Wenn wir im Tierheim <code>for tier in self.tiere: print(tier.mache_laut())</code> aufrufen, weiß Python dank Polymorphie zur Laufzeit automatisch, welches Tier welchen Laut von sich gibt – ohne eine einzige <code>if/elif</code>-Typabfrage!
</div>
</section>
<!-- 4. Persistenz & Factory-Muster -->
<section class="card">
<h2>4. 💾 Savegame-Persistenz mit dem Factory-Muster</h2>
<p>
Beim Speichern als JSON-Datei wandeln wir jedes Tier-Objekt in ein Dictionary um und ergänzen den Schlüssel <code>"art": "Hund"</code>.
Beim Laden liest die <strong>Factory-Methode</strong> <code>Tier.from_dict(data)</code> diesen Schlüssel aus und erzeugt automatisch die exakte Unterklasse:
</p>
<div class="code-container">
<div class="code-header">
<div class="code-dots">
<span class="code-dot dot-red"></span>
<span class="code-dot dot-yellow"></span>
<span class="code-dot dot-green"></span>
</div>
<span>Python (Factory-Methode mit Type-Discriminator)</span>
</div>
<pre><span class="kw">@classmethod</span>
<span class="kw">def</span> <span class="fn">from_dict</span>(<span class="var">cls</span>, <span class="var">data</span>: <span class="cls">dict</span>) -> <span class="cls">Tier</span>:
<span class="var">art</span> = <span class="var">data</span>.<span class="fn">get</span>(<span class="str">"art"</span>, <span class="str">"Tier"</span>)
<span class="kw">if</span> <span class="var">art</span> == <span class="str">"Hund"</span>:
<span class="kw">return</span> <span class="cls">Hund</span>(<span class="var">name</span>=<span class="var">data</span>[<span class="str">"name"</span>], <span class="var">alter</span>=<span class="var">data</span>[<span class="str">"alter"</span>], <span class="var">gewicht</span>=<span class="var">data</span>[<span class="str">"gewicht"</span>], <span class="var">rasse</span>=<span class="var">data</span>.<span class="fn">get</span>(<span class="str">"rasse"</span>, <span class="str">"Mischling"</span>), ...)
<span class="kw">elif</span> <span class="var">art</span> == <span class="str">"Katze"</span>:
<span class="kw">return</span> <span class="cls">Katze</span>(...)
<span class="kw">elif</span> <span class="var">art</span> == <span class="str">"Vogel"</span>:
<span class="kw">return</span> <span class="cls">Vogel</span>(...)
<span class="kw">else</span>:
<span class="kw">return</span> <span class="cls">Tier</span>(...)</pre>
</div>
</section>
<!-- 5. Projekt-Checkliste -->
<section class="card">
<h2>5. ✅ Deine Projekt-Checkliste</h2>
<p>Arbeite die folgenden 5 Abschnitte in der Datei <code><a href="aufgabe.py" style="color: inherit; text-decoration: underline;">aufgabe.py</a></code> der Reihe nach ab:</p>
<ul class="checklist">
<li class="check-item">
<strong>1. Eigene Exceptions:</strong> <code>TierheimFehler</code>, <code>ValidierungsFehler</code>, <code>TierNichtGefundenFehler</code>, <code>KapazitaetUeberschrittenFehler</code>.
</li>
<li class="check-item">
<strong>2. Basisklasse <code>Tier</code>:</strong> Validierung von Name, Alter, Gewicht im <code>__init__</code>, Methoden <code>fuettern()</code>, <code>impfen()</code>, <code>to_dict()</code> und Factory-Methode <code>from_dict()</code>.
</li>
<li class="check-item">
<strong>3. Kindklassen <code>Hund</code>, <code>Katze</code>, <code>Vogel</code>:</strong> Vererbung mit <code>super()</code>, artspezifische Attribute &amp; Methoden (<code>gassi_gehen()</code>, <code>kratzen()</code>, <code>fliegen()</code>) und polymorphes <code>mache_laut()</code>.
</li>
<li class="check-item">
<strong>4. Geschäftslogik <code>Tierheim</code>:</strong> Tieraufnahme mit Kapazitätsprüfung, Vermittlung/Entlassen, Filter nach Art/Impfung/Hunger, Statistiken (Ø Alter, Gewicht) und JSON-/CSV-Persistenz.
</li>
<li class="check-item">
<strong>5. Benutzeroberfläche <code>TierheimApp</code>:</strong> Tkinter-Events mit dem Model verknüpfen, try-except Fehlerabfang und dynamische Statusleisten-Meldungen.
</li>
</ul>
</section>
<!-- 6. Lösungstipps & Details -->
<section class="card">
<h2>6. 💡 Ausklappbare Hilfestellungen &amp; Tipps</h2>
<details>
<summary>🔍 Tipp zu Schritt 1: Eigene Exceptions definieren</summary>
<div class="details-content">
<p>Eigene Exception-Klassen erben in Python einfach von <code>Exception</code> oder einer übergeordneten Basis-Exception:</p>
<div class="code-container">
<pre><span class="kw">class</span> <span class="cls">TierheimFehler</span>(<span class="cls">Exception</span>):
<span class="kw">pass</span>
<span class="kw">class</span> <span class="cls">ValidierungsFehler</span>(<span class="cls">TierheimFehler</span>):
<span class="kw">pass</span></pre>
</div>
</div>
</details>
<details>
<summary>🔍 Tipp zu Schritt 4: CSV-Export mit dem csv-Modul</summary>
<div class="details-content">
<p>Nutze <code>csv.writer</code> mit <code>newline=""</code> für saubere Tabellenausgabe:</p>
<div class="code-container">
<pre><span class="kw">with</span> <span class="fn">open</span>(<span class="var">dateipfad</span>, <span class="str">"w"</span>, <span class="var">newline</span>=<span class="str">""</span>, <span class="var">encoding</span>=<span class="str">"utf-8"</span>) <span class="kw">as</span> <span class="var">f</span>:
<span class="var">writer</span> = <span class="var">csv</span>.<span class="fn">writer</span>(<span class="var">f</span>)
<span class="var">writer</span>.<span class="fn">writerow</span>([<span class="str">"Art"</span>, <span class="str">"Name"</span>, <span class="str">"Alter"</span>, <span class="str">"Gewicht"</span>, <span class="str">"Geimpft"</span>, <span class="str">"Hunger"</span>, <span class="str">"Details"</span>])
<span class="kw">for</span> <span class="var">t</span> <span class="kw">in</span> <span class="var">self</span>.<span class="attr">tiere</span>:
<span class="var">writer</span>.<span class="fn">writerow</span>([<span class="var">t</span>.<span class="var">__class__</span>.<span class="var">__name__</span>, <span class="var">t</span>.<span class="attr">name</span>, <span class="var">t</span>.<span class="attr">alter</span>, <span class="str">f"{t.gewicht:.1f}"</span>, <span class="str">"Ja"</span> <span class="kw">if</span> <span class="var">t</span>.<span class="attr">geimpft</span> <span class="kw">else</span> <span class="str">"Nein"</span>, <span class="str">f"{t.hunger}%"</span>, <span class="var">t</span>.<span class="fn">get_details</span>()])</pre>
</div>
</div>
</details>
<details>
<summary>🔍 Tipp zu Schritt 5: Fehler im GUI-Controller sanft abfangen</summary>
<div class="details-content">
<p>Damit die Desktop-App bei einer Fehleingabe nicht abstürzt, fange Exceptions im Event-Handler ab:</p>
<div class="code-container">
<pre><span class="kw">try</span>:
<span class="var">self</span>.<span class="attr">tierheim</span>.<span class="fn">tier_aufnehmen</span>(<span class="var">neues_tier</span>)
<span class="var">self</span>.<span class="fn">aktualisiere_ansicht</span>()
<span class="var">self</span>.<span class="fn">setze_status</span>(<span class="str">f"{neues_tier.name} aufgenommen! 🎉"</span>, <span class="var">typ</span>=<span class="str">"success"</span>)
<span class="kw">except</span> <span class="cls">TierheimFehler</span> <span class="kw">as</span> <span class="var">e</span>:
<span class="var">self</span>.<span class="fn">setze_status</span>(<span class="fn">str</span>(<span class="var">e</span>), <span class="var">typ</span>=<span class="str">"warning"</span>)</pre>
</div>
</div>
</details>
</section>
<!-- 7. Testen & Starten -->
<section class="card">
<h2>7. 🧪 Lösung überprüfen &amp; App starten</h2>
<h3>1. Automatische Unittests ausführen:</h3>
<div class="code-container">
<div class="code-header">
<span>Terminal (im Ordner 16_master_abschlussprojekt)</span>
</div>
<pre><code>python3 test_aufgabe.py</code></pre>
</div>
<h3>2. Grafische Desktop-Applikation starten:</h3>
<div class="code-container">
<div class="code-header">
<span>Terminal</span>
</div>
<pre><code>python3 app.py</code></pre>
</div>
<div class="footer-nav">
<a href="../15_parameter_und_container/index.html" class="btn btn-secondary">&larr; Zurück zu Kapitel 15</a>
<a href="../../index.html" class="btn">🏆 Kurs abgeschlossen &ndash; Zur Kursübersicht &rarr;</a>
</div>
</section>
</main>
</div>
</div>
<button type="button" class="sidebar-mobile-toggle"><span>☰ Menü</span></button>
<div class="sidebar-overlay"></div>
<!-- Scripts -->
<script src="../../assets/gamification_data.js"></script>
<script src="../../assets/gamification.js"></script>
<script src="../../assets/interpreter.js"></script>
<script src="../../assets/certificate.js"></script>
<script src="../../assets/parsons.js"></script>
<script src="../../assets/runner.js"></script>
<script src="../../assets/ui_enhancements.js"></script>
<script src="../../assets/sidebar.js"></script>
</body>
</html>