125 lines
11 KiB
TypeScript
125 lines
11 KiB
TypeScript
|
|
import { Exercise } from '../types';
|
|
|
|
export const swaExercises7: Exercise[] = [
|
|
{
|
|
id: 'swa-6-1-ddd-tactical',
|
|
title: '6.1 - SWA - Domain-Driven Design (Tactical)',
|
|
parts: [
|
|
{
|
|
id: '6-1-a',
|
|
prompt: 'Erklären Sie die Unterschiede zwischen Entities und Value Objects.',
|
|
solution: 'Entities haben eine eindeutige, überdauernde Identität (ID) und ihr Zustand kann sich ändern. Zwei Entities sind gleich, wenn ihre IDs gleich sind. Beispiel: Ein Kunde.\n\nValue Objects haben keine Identität und sind unveränderlich (immutable). Ihre Gleichheit basiert auf dem Wert ihrer Attribute. Beispiel: Eine Adresse oder ein Geldbetrag.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-b',
|
|
prompt: 'Was ist ein „Aggregate" und welche Rolle spielt das Aggregate Root?',
|
|
solution: 'Ein Aggregat ist eine Gruppe von fachlich zusammengehörenden Objekten (Entities und Value Objects), die als eine Konsistenz- und Transaktionsgrenze behandelt wird. Das Aggregate Root ist die einzige Entity innerhalb des Aggregats, über die von außen zugegriffen werden darf. Es ist dafür verantwortlich, die Geschäftsregeln (Invarianten) des gesamten Aggregats sicherzustellen.',
|
|
points: 7,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-c',
|
|
prompt: 'Erklären Sie, warum Referenzen zwischen Aggregaten nur über ihre IDs erfolgen sollten.',
|
|
solution: 'Referenzen zwischen Aggregaten sollten nur über IDs erfolgen, um lose Kopplung zu gewährleisten und die Transaktionsgrenzen zu wahren. Eine direkte Objektreferenz würde eine starke Kopplung erzeugen und das Laden großer Objektgraphen provozieren. Zudem könnten so die Konsistenzregeln eines Aggregats von außen umgangen werden.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-d',
|
|
prompt: 'Erklären Sie Domain Events und deren Rolle in der Kommunikation zwischen Aggregaten.',
|
|
solution: 'Domain Events sind Objekte, die ein wichtiges Geschäftsereignis repräsentieren (z.B. "OrderPlaced"). Sie ermöglichen eine lose, asynchrone Kommunikation zwischen Aggregaten. Ein Aggregat publiziert ein Event, und andere Aggregate können darauf reagieren, ohne dass eine direkte Kopplung entsteht. Dies wahrt die Transaktionsgrenzen der Aggregate und ermöglicht eine eventually consistent Architektur.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-e',
|
|
prompt: 'Beschreiben Sie die vier Schichten der DDD-Layered-Architecture und deren Verantwortlichkeiten.',
|
|
solution: '1. User Interface Layer: Präsentation und Benutzerinteraktion.\n2. Application Layer: Koordination der Use Cases, enthält keine Geschäftslogik.\n3. Domain Layer: Das Herz der Anwendung. Enthält die Geschäftslogik, Entities, Value Objects und Aggregate.\n4. Infrastructure Layer: Technische Details wie Datenbankzugriffe, Messaging, externe APIs.',
|
|
points: 7,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-f',
|
|
prompt: 'Was ist ein Repository in DDD?',
|
|
solution: 'Ein Repository kapselt die Logik für den Zugriff auf Aggregate und abstrahiert die Persistierung. Es stellt eine domänenorientierte Schnittstelle zur Verfügung (z.B. `findCustomerById`), deren Implementierung (z.B. via SQL) in der Infrastructure-Schicht liegt. Pro Aggregat-Root gibt es ein Repository.',
|
|
points: 5,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '6-1-g',
|
|
prompt: 'Was ist ein Anemic Domain Model und warum ist es ein Anti-Pattern?',
|
|
solution: 'Ein Anemic Domain Model ist ein Modell, bei dem die Domänenobjekte (Entities) nur Daten und Getter/Setter enthalten, aber keine Geschäftslogik. Die Logik wird stattdessen in Service-Klassen ausgelagert. Es ist ein Anti-Pattern, weil es die Prinzipien der Objektorientierung (Kapselung von Daten und Verhalten) verletzt, zu verstreuter Logik führt und die Wartbarkeit erschwert.',
|
|
points: 6,
|
|
type: 'text',
|
|
}
|
|
],
|
|
explanation: '### Lösungserklärung\n\n**Tactical Design** ist der Teil von DDD, der sich mit den konkreten Entwurfsmustern innerhalb eines Bounded Context befasst.\n\n- **Entities & Value Objects**: Die grundlegenden Bausteine. **Entities** haben eine ID, **Value Objects** nicht.\n- **Aggregate**: Eine Gruppe von Objekten, die eine **Konsistenzgrenze** bilden. Änderungen am Aggregat geschehen immer in einer einzigen Transaktion. Der **Aggregate Root** ist der einzige Einstiegspunkt und schützt die Geschäftsregeln (Invarianten) des Aggregats.\n- **Referenzen per ID**: Um Aggregate lose zu koppeln, verweisen sie aufeinander nur über IDs, nicht über direkte Objektreferenzen.\n- **Domain Events**: Werden für die **asynchrone Kommunikation** zwischen Aggregaten genutzt, um die lose Kopplung aufrechtzuerhalten.\n- **Layered Architecture**: Die klassische DDD-Architektur trennt UI, Application, Domain und Infrastructure. Die Abhängigkeiten zeigen immer nach innen zur Domain.\n- **Repository**: Abstrahiert den Datenbankzugriff für ein Aggregat. Die Schnittstelle gehört zur Domäne, die Implementierung zur Infrastruktur.\n- **Anemic Domain Model**: Ein Anti-Pattern, bei dem Objekte nur Datenhalter sind und die Logik in Services ausgelagert wird. Dies widerspricht dem DDD-Ziel, Daten und Verhalten zu kapseln.\n\n### Quellen\n*Folien 6.1, Seite 23-48*'
|
|
},
|
|
{
|
|
id: 'swa-7-1-heuristiken',
|
|
title: '7.1 - SWA - Heuristiken',
|
|
parts: [
|
|
{
|
|
id: '7-1-a',
|
|
prompt: 'Was bedeutet Heuristik im Kontext von Softwarearchitektur?',
|
|
solution: 'Eine Heuristik ist eine erfahrungsbasierte Regel oder ein Prinzip, das eine Abkürzung zu einer guten, aber nicht notwendigerweise optimalen Lösung bietet. In der Softwarearchitektur sind dies bewährte Praktiken und Entwurfsmuster, die bei Trade-off-Entscheidungen helfen.',
|
|
points: 4,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-b',
|
|
prompt: 'Erläutern Sie die Heuristiken "Low Coupling" und "High Cohesion".',
|
|
solution: 'Low Coupling (Lose Kopplung) bedeutet, die Abhängigkeiten zwischen Komponenten zu minimieren. Komponenten sollten so unabhängig wie möglich sein. \nHigh Cohesion (Hoher Zusammenhalt) bedeutet, dass die Elemente innerhalb einer Komponente fachlich eng zusammengehören und eine klar definierte, gemeinsame Aufgabe erfüllen. Beide Prinzipien zusammen führen zu gut strukturierten, wartbaren Systemen.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-c',
|
|
prompt: 'Erläutern Sie das "Single Responsibility Principle" (SRP) und "Information Hiding".',
|
|
solution: 'SRP besagt, dass eine Klasse/Modul nur einen einzigen Grund zur Änderung haben sollte, also nur eine Verantwortlichkeit. \nInformation Hiding (Geheimnisprinzip) besagt, dass Implementierungsdetails einer Komponente nach außen verborgen sein sollten und die Interaktion nur über eine definierte Schnittstelle erfolgt. Dies reduziert die Kopplung.',
|
|
points: 5,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-d',
|
|
prompt: 'Erläutern Sie das "Open Closed Principle" (OCP) und das "Liskov Substitution Principle" (LSP).',
|
|
solution: 'OCP: Software-Einheiten sollen offen für Erweiterungen, aber geschlossen für Modifikationen sein. Man fügt neues Verhalten hinzu, ohne bestehenden Code zu ändern (z.B. durch Interfaces).\nLSP: Unterklassen müssen ihre Oberklassen jederzeit ersetzen können, ohne das Programmverhalten zu ändern. "is-a"-Beziehung.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-e',
|
|
prompt: 'Erläutern Sie das "Interface Segregation Principle" (ISP) und das "Dependency Inversion Principle" (DIP).',
|
|
solution: 'ISP: Bevorzuge kleine, client-spezifische Interfaces statt großer, allgemeiner Interfaces. Clients sollen nicht von Methoden abhängen, die sie nicht verwenden.\nDIP: High-level-Module sollen nicht von Low-level-Modulen abhängen. Beide sollen von Abstraktionen (Interfaces) abhängen. Dies kehrt die Abhängigkeitsrichtung um.',
|
|
points: 6,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-f',
|
|
prompt: 'Erläutern Sie die Heuristik "Don\'t Repeat Yourself" (DRY) und "Keep It Small and Simple" (KISS).',
|
|
solution: 'DRY: Jede Information oder Logik sollte nur eine einzige, eindeutige Repräsentation im System haben. Vermeide Redundanz.\nKISS: Bevorzuge Einfachheit. Wende komplexe Muster nicht an, wo eine einfache Lösung ausreicht. Finde die richtige Balance zwischen guter Struktur und unnötiger Komplexität.',
|
|
points: 5,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-g',
|
|
prompt: 'Was ist das „God-Object"-Antipattern und welche Heuristik verletzt es primär?',
|
|
solution: 'Ein God-Object ist ein Anti-Pattern, bei dem eine einzelne Klasse oder Komponente zu viele, nicht zusammengehörende Verantwortlichkeiten übernimmt. Sie wird riesig und ist schwer zu warten und zu testen.\n\nEs verletzt primär das "Single Responsibility Principle" (bzw. die Heuristik der "Separation of Concerns" und "High Cohesion").',
|
|
points: 5,
|
|
type: 'text',
|
|
},
|
|
{
|
|
id: '7-1-h',
|
|
prompt: 'Bei Quasar sollte AT-Software vermieden werden. Wieso?',
|
|
solution: 'AT-Software (Application + Technology) ist Software, die Fachlogik (A) und technische Belange (T) stark vermischt. Dies sollte vermieden werden, weil es zu hoher Kopplung führt, die Wartbarkeit erschwert und die Wiederverwendbarkeit praktisch unmöglich macht. Fachliche Änderungen wirken sich auf technische Teile aus und umgekehrt.',
|
|
points: 5,
|
|
type: 'text',
|
|
},
|
|
],
|
|
explanation: '### Lösungserklärung\n\n**Heuristiken** sind bewährte "Faustregeln", die Architekten helfen, gute Designentscheidungen zu treffen.\n\n- **Low Coupling & High Cohesion**: Das wichtigste Duo. **Hohe Kohäsion** innerhalb einer Komponente (alles darin gehört zusammen), **lose Kopplung** zwischen den Komponenten (sie sind möglichst unabhängig voneinander).\n- **SOLID-Prinzipien** sind eine Sammlung von fünf zentralen Heuristiken:\n - **S**ingle Responsibility Principle (SRP): Eine Klasse, eine Aufgabe.\n - **O**pen-Closed Principle (OCP): Erweiterbar, ohne den Code zu ändern.\n - **L**iskov Substitution Principle (LSP): Unterklassen müssen ihre Oberklassen vollständig ersetzen können.\n - **I**nterface Segregation Principle (ISP): Lieber viele kleine, spezifische Interfaces als ein großes.\n - **D**ependency Inversion Principle (DIP): Abhängigkeiten sollten auf Abstraktionen (Interfaces) zeigen, nicht auf konkrete Implementierungen.\n- **Weitere wichtige Heuristiken**: **DRY** (vermeide Redundanz), **KISS** (halte es einfach) und **Information Hiding** (verberge Implementierungsdetails).\n\nDas **God-Object**-Antipattern ist ein klassisches Beispiel für die Verletzung des **SRP** und der **hohen Kohäsion**. Es ist eine Klasse, die zu viele Verantwortungen an sich reißt, was zu einem schwer wartbaren System führt. Ähnlich problematisch ist **AT-Software**, die Fach- und Technik-Code vermischt.\n\n### Quellen\n*Folien 7.1, Seite 3-37*'
|
|
}
|
|
];
|