import { Exercise } from '../types'; export const swaExercisesExamples: Exercise[] = [ { id: 'swa-ex-datamodel-1', title: 'Beispiel: Fachliches Datenmodell (Bibliothek)', parts: [ { id: 'a', prompt: 'Erstellen Sie ein fachliches Datenmodell in Mermaid-Syntax für ein einfaches öffentliches Bibliothekssystem. Das System soll Bücher, Mitglieder und Ausleihen verwalten. Berücksichtigen Sie die folgenden Konzepte:\n- **Buch**: mit ISBN, Titel und Autor.\n- **Mitglied**: mit Mitglieds-ID, Name und Adresse.\n- **Ausleihe**: die ein Mitglied mit einem Buch verbindet und ein Ausleih- sowie ein Rückgabedatum hat.', solution: '```mermaid\nclassDiagram\n class Buch {\n +ISBN isbn\n +Titel titel\n +Autor autor\n }\n class Mitglied {\n +MitgliedsID id\n +Name name\n +Adresse adresse\n }\n class Ausleihe {\n +Datum ausleihdatum\n +Datum rueckgabedatum\n }\n\n Mitglied "1" -- "0..*" Ausleihe : leiht aus\n Buch "1" -- "0..*" Ausleihe : wird ausgeliehen\n```', points: 8, type: 'mermaid', } ], explanation: '### Lösungserklärung\n\nEin gutes fachliches Datenmodell konzentriert sich auf die **Konzepte der Domäne** und deren Beziehungen, nicht auf technische Details. Es verwendet fachliche Datentypen, um die Bedeutung der Daten zu verdeutlichen.\n\n**Bestandteile des Modells:**\n\n1. **Entitäten**: Dies sind die zentralen Objekte mit einer eindeutigen Identität.\n * `Buch`: Jedes Buch ist einzigartig, auch wenn es den gleichen Titel wie ein anderes hat (z.B. durch eine Inventarnummer, die hier durch die `ISBN` repräsentiert wird).\n * `Mitglied`: Jedes Mitglied ist durch seine `MitgliedsID` eindeutig identifizierbar.\n * `Ausleihe`: Jede einzelne Ausleihe ist ein einzigartiges Ereignis, selbst wenn dasselbe Mitglied dasselbe Buch später erneut ausleiht.\n\n2. **Fachliche Datentypen (Value Objects)**: Anstatt primitive Typen wie `string` oder `int` zu verwenden, definieren wir spezifischere Typen, die eine fachliche Bedeutung tragen. Im Diagramm sind dies z.B. `ISBN`, `Titel`, `MitgliedsID`, `Adresse`, `Datum`. Dies hat mehrere Vorteile:\n * **Verständlichkeit**: Es ist sofort klar, was gemeint ist.\n * **Validierung**: Ein `ISBN`-Typ könnte eine eingebaute Validierungslogik enthalten, um sicherzustellen, dass nur gültige ISBNs gespeichert werden.\n * **Typsicherheit**: Man kann nicht versehentlich eine `MitgliedsID` einem `ISBN`-Feld zuweisen.\n\n3. **Beziehungen und Kardinalitäten**:\n * `Mitglied "1" -- "0..*" Ausleihe`: Ein Mitglied kann keine, eine oder viele Ausleihen haben. Jede Ausleihe gehört aber zu genau einem Mitglied.\n * `Buch "1" -- "0..*" Ausleihe`: Ein spezifisches Exemplar eines Buches kann über die Zeit mehrfach ausgeliehen werden (oder auch nie). Jede Ausleihe bezieht sich auf genau ein Buch.\n\nDieses Modell bildet die statische Struktur der Bibliotheksdomäne klar und verständlich ab und dient als exzellente Grundlage für weitere Diskussionen und die Implementierung.' }, { id: 'swa-ex-datamodel-2', title: 'Beispiel: Fachliches Datenmodell (Tierheim)', parts: [ { id: 'a', prompt: 'Erstellen Sie ein fachliches Datenmodell in Mermaid-Syntax für eine Tiervermittlungs-Agentur. Das Modell soll Tiere, Interessenten und Adoptionsanträge abbilden.\n- **Tier**: mit Tier-ID, Name, Spezies (z.B. Hund, Katze) und Status (z.B. verfügbar, reserviert, adoptiert).\n- **Interessent**: mit Interessenten-ID, Name und Kontaktdaten.\n- **Antrag**: der einen Interessenten mit einem Tier verbindet und einen Antragsstatus (z.B. eingereicht, geprüft, genehmigt, abgelehnt) hat.', solution: '```mermaid\nclassDiagram\n class Tier {\n +TierID id\n +Name name\n +Spezies spezies\n +TierStatus status\n }\n class Interessent {\n +InteressentID id\n +Name name\n +Kontaktdaten kontaktdaten\n }\n class Antrag {\n +AntragsID id\n +AntragsStatus status\n }\n\n Interessent "1" -- "1..*" Antrag : stellt\n Tier "1" -- "1..*" Antrag : ist Gegenstand von\n```', points: 8, type: 'mermaid', } ], explanation: '### Lösungserklärung\n\nDieses Modell fokussiert auf den Prozess der Tiervermittlung. Es trennt klar die Konzepte und deren Zustände, was für einen prozessorientierten Anwendungsfall entscheidend ist.\n\n**Bestandteile des Modells:**\n\n1. **Entitäten**:\n * `Tier`: Ein Tier ist eine Entität mit einem Lebenszyklus innerhalb des Tierheims. Sein `TierStatus` ist ein zentrales Attribut, das den Vermittlungsprozess steuert.\n * `Interessent`: Eine Person, die an einer Adoption interessiert ist. Ihre Identität ist wichtig, um Anträge zuzuordnen.\n * `Antrag`: Der Antrag selbst ist eine Entität, da jeder Antrag einzigartig ist und einen eigenen Lebenszyklus mit verschiedenen Phasen (`AntragsStatus`) durchläuft.\n\n2. **Fachliche Datentypen (Value Objects)**:\n * `TierID`, `InteressentID`, `AntragsID`: Spezifische Identifikatoren, die Typsicherheit gewährleisten.\n * `TierStatus`, `AntragsStatus`: Dies sind Enums oder Value Objects, die einen festen Satz von Zuständen repräsentieren. Dies ist viel besser als die Verwendung von `int` oder `string`, da es Fehleingaben verhindert und die Geschäftsregeln explizit macht.\n * `Spezies`, `Name`, `Kontaktdaten`: Weitere fachliche Datentypen, die Konzepte bündeln und für Klarheit sorgen.\n\n3. **Beziehungen und Kardinalitäten**:\n * `Interessent "1" -- "1..*" Antrag`: Ein Interessent muss mindestens einen Antrag stellen, um im System relevant zu sein, und kann sich für mehrere Tiere bewerben. Jeder Antrag gehört zu genau einem Interessenten.\n * `Tier "1" -- "1..*" Antrag`: Für ein Tier kann es mehrere Anträge geben. Jeder Antrag bezieht sich aber auf genau ein Tier.\n\n**Besonderheiten des Modells**:\nDas Modell trennt die Entität `Interessent` von einem potenziellen `Adoptant`. Ein Interessent wird erst zum Adoptanten, wenn ein `Antrag` den Status `genehmigt` erreicht. Diese prozessuale Logik wäre der nächste Schritt, der auf diesem statischen Modell aufbaut (z.B. in einer Laufzeitsicht).' }, { id: 'swa-ex-bewertung-1', title: 'Beispiel: Bewertung eines Datenmodells (E-Shop)', parts: [ { id: 'a', prompt: 'Bewerten Sie das folgende, fehlerhafte fachliche Datenmodell für einen E-Commerce-Shop. Identifizieren Sie mindestens drei signifikante Schwächen und schlagen Sie Verbesserungen vor.\n\n```mermaid\nclassDiagram\n class User {\n int id\n string name\n string address_line_1\n string address_line_2\n string city\n }\n class Order {\n int id\n List~Product~ items\n }\n class Product {\n int id\n string name\n float price\n }\n User "1" -- "0..*" Order : places\n```', solution: 'Dieses Datenmodell hat mehrere signifikante Schwächen:\n\n1. **Verwendung technischer Primitive**: Das Modell verwendet technische Datentypen wie `int` und `string` anstelle von fachlichen. `string address_line_1` sollte Teil eines `Adresse`-Value-Objects sein. `int id` sollte ein fachlicher Typ wie `KundenID` oder `BestellID` sein.\n\n2. **Verletzung der Datenhoheit / Starke Kopplung**: Die `Order`-Klasse enthält eine `List`. Das bedeutet, eine Bestellung enthält die vollständigen Produktobjekte. Dies ist problematisch, weil sich Produktinformationen (z.B. der Preis) ändern können. Eine Bestellung sollte den Zustand zum Zeitpunkt des Kaufs "einfrieren". Besser wäre es, wenn `Order` eine Liste von `OrderItem`-Value-Objects enthält, die nur die `ProduktID`, den gekauften Preis und die Menge speichern.\n\n3. **Fehlende fachliche Konzepte**: Das Konzept "Kunde" wird nur als `User` bezeichnet, was unpräzise ist. Wichtige Attribute wie das Bestelldatum, der Bestellstatus oder die Gesamtsumme fehlen in der `Order`-Klasse komplett.', points: 9, type: 'text', } ], explanation: '### Detaillierte Erklärung der Bewertung\n\nEin gutes fachliches Datenmodell soll die Realität der Geschäftsdomäne so präzise wie möglich abbilden. Dieses Modell scheitert daran in mehreren Punkten.\n\n**1. Mangelnde fachliche Typisierung (Primitive Obsession)**\n- **Problem**: Die Verwendung von `string`, `int`, `float` verschleiert die eigentliche Bedeutung der Daten. Eine Adresse ist mehr als nur drei Strings; sie ist ein zusammengehöriges Konzept. Ein Preis ist nicht nur eine Fließkommazahl; er hat auch eine Währung.\n- **Verbesserung**: Führen Sie fachliche Datentypen (Value Objects) ein. Erstellen Sie eine `Adresse`-Klasse, die Straße, Stadt, PLZ etc. bündelt. Erstellen Sie eine `Geldbetrag`-Klasse, die Wert und Währung kombiniert. Definieren Sie spezifische ID-Typen wie `KundenID`, `ProduktID`, `BestellID`, um Typsicherheit zu erhöhen.\n\n**2. Starke Kopplung und falsche Komposition**\n- **Problem**: `Order` enthält eine Liste von `Product`-Objekten. Das bedeutet, wenn man eine Bestellung lädt, lädt man auch alle zugehörigen, aktuellen Produktinformationen. Was passiert, wenn sich der Preis eines Produkts ändert, nachdem die Bestellung aufgegeben wurde? Der alte Preis in der Bestellung würde überschrieben, was falsch ist. Die Bestellung ist an die *aktuelle* Produktdefinition gekoppelt.\n- **Verbesserung**: Entkoppeln Sie die Bestellung vom Produktkatalog. Eine `Order` sollte eine Liste von `OrderItem` (Bestellposition) enthalten. Ein `OrderItem` ist ein Value Object, das die `ProduktID` als Referenz, die `Menge` und den `PreisZumKaufzeitpunkt` speichert. So bleibt die Bestellung historisch korrekt und ist von späteren Änderungen im Produktkatalog unabhängig.\n\n**3. Unvollständigkeit und unpräzise Benennung**\n- **Problem**: Dem Modell fehlen essenzielle Informationen. Eine Bestellung ohne Datum, Status oder Summe ist unbrauchbar. Der Begriff `User` ist zu generisch. Ist jeder User ein Kunde? Was ist mit Administratoren?\n- **Verbesserung**: Benennen Sie `User` in `Kunde` um, um die Rolle im Kontext des E-Shops klar zu machen. Fügen Sie der `Order`-Klasse wichtige Attribute wie `bestelldatum: Datum`, `status: BestellStatus` und `gesamtsumme: Geldbetrag` hinzu.' }, { id: 'swa-ex-adr-1', title: 'Beispiel: ADR für Datenbankwahl (Social App)', parts: [ { id: 'a', prompt: 'Sie entwerfen eine neue Social-Media-App mit einem Newsfeed. Die Leselast (Feed abrufen) wird extrem hoch sein, während die Schreiblast (neue Posts) moderat ist. Horizontale Skalierbarkeit und hohe Verfügbarkeit sind die wichtigsten Qualitätsziele. Formulieren Sie einen ADR (nur Kontext, Entscheidung, Konsequenzen) für die Wahl der primären Datenbank.', solution: '**Kontext:**\nWir benötigen eine Datenbank für unsere Social-Media-App, die einen Newsfeed mit Posts, Kommentaren und Likes verwaltet. Die erwarteten Zugriffsmuster sind leselastig (viele Benutzer scrollen durch Feeds). Die wichtigsten Qualitätsanforderungen sind extrem hohe Verfügbarkeit und die Fähigkeit zur horizontalen Skalierung, um Millionen von Benutzern zu unterstützen. Starke Konsistenz (ACID) ist für Feed-Daten nicht zwingend erforderlich; eventual consistency ist akzeptabel. Die Daten sind semi-strukturiert und haben oft Beziehungen (Benutzer -> Posts -> Kommentare).\n\n**Entscheidung:**\nWir entscheiden uns für die Verwendung einer Wide-Column NoSQL-Datenbank wie Apache Cassandra oder Amazon DynamoDB als primären Datenspeicher. Wir werden unsere Daten denormalisieren und für die primären Lese-Queries optimieren (z.B. Posts eines Benutzers in einer einzigen Partition speichern).\n\n**Konsequenzen:**\n* **Positiv:**\n * Exzellente horizontale Skalierbarkeit und hohe Schreib- und Leseleistung unter Last.\n * Hohe Verfügbarkeit durch die verteilte und replizierte Natur der Datenbank.\n * Flexibles Schema erleichtert zukünftige Feature-Entwicklungen.\n* **Negativ:**\n * Eventual Consistency: Daten sind möglicherweise nicht sofort nach dem Schreiben auf allen Knoten sichtbar. Dies muss in der Anwendungslogik berücksichtigt werden.\n * Keine komplexen Joins: Ad-hoc-Abfragen sind schwierig. Daten müssen für spezifische Abfragen modelliert (denormalisiert) werden, was zu Datenredundanz führt.\n * Das Entwicklungsteam muss neue Datenmodellierungstechniken erlernen, die sich von relationalen Datenbanken unterscheiden.', points: 10, type: 'text', } ], explanation: '### Detaillierte Erklärung des ADR\n\nEin guter ADR (Architecture Decision Record) ist präzise, nachvollziehbar und ehrlich über die Konsequenzen. Dieser ADR zur Datenbankwahl ist ein klassisches Beispiel für eine grundlegende Architekturentscheidung.\n\n**Analyse des Kontexts:**\nDer Kontext beschreibt klar das **Problem** und die **Rahmenbedingungen (Constraints)**. Hier sind die Schlüsselwörter: "leselastig", "horizontale Skalierbarkeit", "hohe Verfügbarkeit" und "eventual consistency ist akzeptabel". Diese Treiber deuten stark auf eine NoSQL-Lösung hin und schließen traditionelle relationale Datenbanken für diesen speziellen Anwendungsfall eher aus, da diese oft schwerer horizontal zu skalieren sind.\n\n**Analyse der Entscheidung:**\nDie Entscheidung ist **konkret** und **begründet**. Sie benennt nicht nur eine Technologiekategorie ("NoSQL"), sondern eine spezifische Art ("Wide-Column") und sogar Beispiele ("Cassandra", "DynamoDB"). Wichtig ist auch der Zusatz, *wie* die Technologie genutzt werden soll: "denormalisieren und für Lese-Queries optimieren". Das zeigt, dass die Konsequenzen der Entscheidung verstanden wurden.\n\n**Analyse der Konsequenzen:**\nDies ist oft der wichtigste Teil eines ADR. Er zeigt, dass ein **Trade-off** gemacht wurde und die Nachteile bewusst in Kauf genommen werden. \n- Die **positiven** Konsequenzen mappen direkt auf die im Kontext genannten Qualitätsziele (Skalierbarkeit, Verfügbarkeit).\n- Die **negativen** Konsequenzen sind ehrlich und realistisch. Sie sprechen die größten Herausforderungen von NoSQL-Datenbanken an: \n 1. **Eventual Consistency**: Dies ist ein fundamentaler Unterschied zu ACID und hat Auswirkungen auf das gesamte Systemdesign. Der ADR macht klar, dass dies bedacht wurde.\n 2. **Datenmodellierung**: Der Hinweis auf Denormalisierung und fehlende Joins ist entscheidend. Er zeigt, dass der damit verbundene Mehraufwand und die andere Denkweise erkannt wurden.\n 3. **Team-Fähigkeiten**: Die Notwendigkeit, dass das Team umlernen muss, ist eine wichtige organisatorische Konsequenz.\n\nInsgesamt dokumentiert dieser ADR eine fundierte, abgewogene Entscheidung, die für jeden (auch für neue Teammitglieder in der Zukunft) nachvollziehbar ist.' }, { id: 'swa-ex-contextmap-1', title: 'Beispiel: Context Map (Lernplattform)', parts: [ { id: 'a', prompt: 'Entwerfen Sie eine Context Map in Mermaid-Syntax für eine Online-Lernplattform. Berücksichtigen Sie die Bounded Contexts: `CourseCatalog` (Verwaltung der Kurse), `StudentEnrollment` (Einschreibung der Studenten), `Forum` (Diskussionsforum) und `Payment` (externe Zahlungsabwicklung). Definieren Sie plausible Beziehungen zwischen den Kontexten.', solution: '```mermaid\ngraph TD\n subgraph "Online-Lernplattform"\n A(CourseCatalog) -- "Open Host Service" --> B(StudentEnrollment)\n D(Forum) -- "Shared Kernel (User Profile)" --> B\n end\n\n B -- "Anti-Corruption Layer" --> C{Payment Gateway}\n\n linkStyle 0 stroke-width:2px,fill:none,stroke:green;\n linkStyle 1 stroke-width:2px,fill:none,stroke:orange;\n linkStyle 2 stroke-width:2px,fill:none,stroke:red;\n```\n*Legende: Grün=OHS, Orange=Shared Kernel, Rot=ACL*', points: 9, type: 'mermaid', } ], explanation: '### Detaillierte Erklärung der Context Map\n\nEine Context Map ist ein strategisches DDD-Werkzeug, das die Beziehungen zwischen verschiedenen Bounded Contexts visualisiert. Sie ist entscheidend für das Verständnis der Systemlandschaft und die Organisation der Team-Zusammenarbeit.\n\n**Beziehungs-Patterns und ihre Begründung:**\n\n1. **CourseCatalog -- "Open Host Service" --> StudentEnrollment**\n * **Pattern**: Open Host Service (OHS). Der `CourseCatalog`-Kontext bietet eine stabile, gut dokumentierte API (den "Service") an, die von anderen Kontexten (den "Clients") genutzt werden kann. \n * **Begründung**: Der Kurs-Katalog ist eine zentrale, stabile Ressource. Das `StudentEnrollment`-Team muss wissen, welche Kurse existieren, um Einschreibungen zu ermöglichen. Der Katalog diktiert das Modell, `StudentEnrollment` konsumiert es. Dies ist eine sehr typische Beziehung für eine zentrale, datenliefernde Komponente.\n\n2. **Forum -- "Shared Kernel (User Profile)" --> StudentEnrollment**\n * **Pattern**: Shared Kernel. Zwei Teams einigen sich darauf, einen kleinen Teil ihres Modells (und des Codes) zu teilen. \n * **Begründung**: Sowohl für die Einschreibung als auch für das Forum wird ein Benutzerprofil mit Namen, E-Mail etc. benötigt. Anstatt dieses Modell in beiden Kontexten redundant zu entwickeln, wird es in einer gemeinsamen Bibliothek (dem Shared Kernel) gepflegt. \n * **Trade-off**: Dies führt zu einer engen Kopplung. Jede Änderung am Shared Kernel muss von beiden Teams abgesegnet und koordiniert werden. Es sollte nur für sehr stabile, wirklich gemeinsame Konzepte verwendet werden.\n\n3. **StudentEnrollment -- "Anti-Corruption Layer" --> Payment Gateway**\n * **Pattern**: Anti-Corruption Layer (ACL). Eine explizite Übersetzungsschicht, die das eigene Domänenmodell vor den Einflüssen eines externen oder veralteten Systems schützt.\n * **Begründung**: Der `Payment Gateway` ist ein externes System mit seinem eigenen, oft komplizierten und nicht idealen Datenmodell (z.B. `TransactionRequest`, `PaymentResponse`). Der ACL übersetzt zwischen dem Modell des `StudentEnrollment`-Kontextes (z.B. `Invoice`, `PaymentConfirmation`) und dem externen Modell. Dadurch bleibt unser eigenes Domänenmodell sauber und unabhängig. Wenn der Zahlungsanbieter gewechselt wird, muss nur der ACL angepasst werden, nicht der gesamte `StudentEnrollment`-Kontext.' }, { id: 'swa-ex-lod-1', title: 'Beispiel: Heuristik (Law of Demeter)', parts: [ { id: 'a', prompt: 'Der folgende Java-Code verletzt die "Law of Demeter" (LoD) Heuristik: \n`String strasse = bestellung.getKunde().getAdresse().getStrasse();`\n\n1. Erklären Sie, warum dieser Code die Heuristik verletzt.\n2. Schreiben Sie eine refaktorisierte Version, die die Heuristik einhält.', solution: '1. **Verletzung**: Der Code verletzt die LoD, weil die aufrufende Methode tief in die interne Struktur des `bestellung`-Objekts greift. Sie "spricht nicht nur mit ihrem direkten Freund" (`bestellung`), sondern auch mit "Freunden von Freunden" (`kunde` und `adresse`). Dies erzeugt eine starke Kopplung an die Implementierungsdetails von `Kunde` und `Adresse`. Ändert sich die Struktur der `Adresse`-Klasse, muss dieser Aufruf ebenfalls geändert werden.\n\n2. **Refaktorisierung**:\nAuf der `Bestellung`-Klasse wird eine neue Methode hinzugefügt, die die interne Navigation verbirgt:\n```java\n// In der aufrufenden Methode:\nString strasse = bestellung.getKundenStrasse();\n\n// Neue Methode in der Klasse Bestellung:\npublic String getKundenStrasse() {\n return kunde.getAdresse().getStrasse();\n}\n```', points: 8, type: 'text', } ], explanation: '### Detaillierte Erklärung zur Law of Demeter (LoD)\n\nDie "Law of Demeter" ist eine Heuristik für lose Kopplung. Sie wird oft als "Prinzip des geringsten Wissens" oder "Sprich nur mit deinen direkten Freunden" zusammengefasst. Das Ziel ist es, die Abhängigkeiten zwischen Objekten zu minimieren.\n\n**Warum ist die ursprüngliche Version schlecht?**\nDer Aufruf `bestellung.getKunde().getAdresse().getStrasse()` erzeugt eine **Wissenskette (Train Wreck)**. Die aufrufende Methode muss wissen:\n- dass eine `Bestellung` einen `Kunde` hat.\n- dass ein `Kunde` eine `Adresse` hat.\n- dass eine `Adresse` eine `Strasse` hat.\n\nDiese Kette von Abhängigkeiten macht den Code **fragil**. Wenn das `Kunde`-Objekt morgen entscheidet, seine Adress-Struktur zu ändern (z.B. in eine Liste von Adressen), bricht der aufrufende Code, obwohl er sich eigentlich nur für die `Bestellung` interessiert. Er ist zu stark an die *Implementierung* seiner Nachbarn gekoppelt.\n\n**Warum ist die refaktorisierte Version besser?**\nDie neue Methode `bestellung.getKundenStrasse()` ist eine Form von **Delegation**. Die `Bestellung`-Klasse übernimmt die Verantwortung, die Information zu beschaffen. Der Aufrufer muss die interne Struktur nicht mehr kennen. Er spricht nur noch mit seinem direkten Freund, der `bestellung`.\n\n- **Vorteile**:\n - **Lose Kopplung**: Der Aufrufer hängt nur noch von der `Bestellung`-Schnittstelle ab, nicht mehr von `Kunde` oder `Adresse`.\n - **Bessere Kapselung**: Die interne Struktur von `Bestellung` und seinen Bestandteilen ist verborgen (**Information Hiding**).\n - **Einfachere Wartung**: Wenn sich die Adress-Struktur ändert, muss nur die Methode `getKundenStrasse()` innerhalb der `Bestellung`-Klasse angepasst werden. Alle Aufrufer bleiben unberührt.\n\nDie Einhaltung der LoD führt zu wartbareren, flexibleren und robusteren Systemen.' }, ];