Aufgabe 09 - Jahresprojekt Sprint 2 - Review, ISP und DIP
Lernziele
Abschnitt betitelt „Lernziele“- Du zerlegst ein zu breites Interface nach dem Interface Segregation Principle in kleine, gezielte Schnittstellen.
- Du schließt Sprint 2 mit Review, Retrospektive und Release ab.
- Du ersetzt im Jahresprojekt eine fest verdrahtete Abhängigkeit nach dem Dependency Inversion Principle durch eine hereingereichte Abstraktion und wählst die konkreten Klassen an einer einzigen Stelle.
- Du testest Fachlogik deines Projekts ohne Datenbank, indem du eine Implementierung im Arbeitsspeicher hereinreichst.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Dritte und letzte Woche von Sprint 2. Nach Review und Retrospektive geht es um die zwei letzten Buchstaben von SOLID (Kapitel 14): I (kein Client hängt von Methoden ab, die er nicht braucht) und D (die Geschäftslogik kennt nur die Abstraktion, die Wahl der konkreten Klasse trifft eine einzige Stelle). In fast jedem Jahresprojekt gibt es eine Stelle, an der die Fachlogik ihre Datenbank oder ihren Speicher selbst erzeugt. Genau dort lohnt sich DIP am meisten, denn danach lässt sich die Logik ohne Datenbank testen.
Die Kata: Geräte der Medienwerkstatt. Der Startcode:
interface StudioDevice { record(seconds: number): string; play(file: string): void; printLabel(text: string): void;}
class Microphone implements StudioDevice { record(seconds: number): string { return `take-${seconds}s.wav`; } play(): void { throw new Error("a microphone cannot play"); } printLabel(): void { throw new Error("a microphone cannot print"); }}
class Speaker implements StudioDevice { record(): string { throw new Error("a speaker cannot record"); } play(file: string): void { console.log(`playing ${file}`); } printLabel(): void { throw new Error("a speaker cannot print"); }}
class Playlist { constructor(private readonly device: StudioDevice) {}
playAll(files: string[]): void { for (const file of files) this.device.play(file); }}Dafür brauchst du:
- Kapitel 14 Entwurfsmuster I – SOLID: I und D (Fat Interface, High-Level- und Low-Level-Modul, hereingereichte Abstraktion, Composition Root, DIP gegen Dependency Injection gegen IoC-Container, Zusammenspiel der fünf Prinzipien).
- Kapitel 05 bis 07 für Review, Retrospektive und Release.
- Euer Design-Review aus Aufgabe 07 und 08.
Allgemein
Abschnitt betitelt „Allgemein“Projektordner anlegen siehe https://qiz.at/projektordner
- Lies vorher kurz https://qiz.at/assignmentsabgabe durch.
- Nur vollständige Abgaben (siehe https://qiz.at/rules) können positiv bewertet werden.
- Abgabe- und Testdetails siehe https://qiz.at/assignmentsabgabe
- Abgegeben wird dein Projektordner mit der Kata (Code und
README.md) und den Links auf Sprint-Protokoll, Release, Issues, Merge Requests und Abschnitte imdocs/design-review.mddes Jahresprojekts. Bezeichner und Kommentare im Code sind Englisch. - Wer was beigetragen hat, zeigen Board, Merge Requests und
/spend-Einträge (Kapitel 07).
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“- Kata: Liste alle Methoden auf, zu denen eine Klasse gezwungen wird, obwohl sie nichts damit anfangen kann. Zerlege
StudioDevicein kleine Schnittstellen, sodass keine Klasse mehr eine sinnlose Methode enthält undPlaylistnur noch von dem abhängt, was es braucht. Prüfe mitnpx tsc --noEmit, dass alles übersetzt. - Review von Sprint 2: Vorführung Story für Story gegen die Akzeptanzkriterien, Sprint-Protokoll mit abgenommenen und zurückgelegten Stories, Sprint-Ziel erreicht oder nicht (mit Ursache) und Velocity. Die Lehrkraft geht während der Praxiszeit von Team zu Team (etwa zehn Minuten je Team); bis sie bei euch ist, arbeitet ihr an der Kata und am Projektteil weiter.
- Retrospektive: Überprüft zuerst die Maßnahme aus Sprint 1 und haltet eine neue, überprüfbare Maßnahme mit verantwortlicher Person fest.
Tipp: Frag bei jeder Klasse der Kata: Würde ein Client, der nur diese Klasse benutzt, alle Methoden des Interfaces aufrufen wollen?
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- alle vier sinnlosen Methoden erkannt sind, keine Klasse nach der Zerlegung eine Methode enthält, die sie nicht kann,
Playlistnur von einer Schnittstelle mitplayabhängt und das Projekt fehlerfrei übersetzt, - das Sprint-Protokoll abgenommene und zurückgelegte Stories, die Bewertung des Sprint-Ziels mit Ursache und die Velocity enthält,
- die alte Maßnahme überprüft ist und die neue Maßnahme überprüfbar ist und eine verantwortliche Person hat.
Wie unter Allgemein.
Wesentlich_vollständig
Abschnitt betitelt „Wesentlich_vollständig“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Release von Sprint 2 nach Kapitel 07 (Release-Merge-Request
devnachmain, Tag, Release-Notes, Milestone schließen). - DIP im Projekt: Sucht die Stelle, an der eure Fachlogik ihren Datenzugriff selbst erzeugt oder direkt importiert (Datenbank-Client, Datei,
fetchauf eine fremde API). Legt dafür ein Issue an und baut in einem Merge Request um: ein Repository-Interface, das nur die Operationen enthält, die die Fachlogik braucht, die bisherige Umsetzung als eine Implementierung davon, die Fachlogik bekommt das Interface über den Konstruktor oder als Parameter hereingereicht. - Wählt die konkreten Klassen an einer Stelle eures Projekts aus (Composition Root) und haltet im Design-Review fest, wo sie liegt.
- Schreibt eine Implementierung im Arbeitsspeicher (
InMemory…) und einen Test der Fachlogik, der damit ohne Datenbank und ohne Netzwerk läuft.
Tipp: Wenn in eurer Fachlogik nach dem Umbau noch ein
newauf eine konkrete Datenbank- oder Client-Klasse steht, ist die Abhängigkeit noch nicht umgekehrt. Bei Next.js ist eine kleine Datei, die Service und Repository zusammensteckt und von den Routen importiert wird, ein brauchbarer Composition Root.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- Release-Merge-Request, Tag, Release und geschlossener Milestone
Sprint 2existieren, - die Fachlogik nur noch vom Repository-Interface abhängt und kein
newauf eine konkrete Datenzugriffsklasse enthält, - die Auswahl der konkreten Klassen an genau einer Stelle steht und diese im Design-Review benannt ist,
- ein Test der Fachlogik mit der Implementierung im Arbeitsspeicher grün läuft.
Wie unter Allgemein.
PlusPlus Aufgabe
Abschnitt betitelt „PlusPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Ergänze einen zweiten Test mit der Implementierung im Arbeitsspeicher, der eine Regel der Fachlogik prüft, die etwas ablehnt.
- ISP im Projekt: Suche zwei Stellen, an denen eine Funktion oder Komponente ein ganzes Objekt verlangt, aber nur einen Teil davon nutzt (zum Beispiel einen ganzen Benutzer, obwohl nur der Name gebraucht wird). Verkleinere den verlangten Typ und halte im Design-Review fest, was dadurch leichter zu testen oder wiederzuverwenden ist.
- Baue den Composition Root zu zwei Konfigurationen aus, die eine Umgebungsvariable auswählt: „production“ (echter Datenzugriff) und „demo“ (Implementierung im Arbeitsspeicher mit Beispieldaten). Weise mit
git diff --statnach, dass die Fachlogik dafür unverändert blieb.
Tipp: In TypeScript genügt oft ein kleinerer Typ wie
{ title: string }statt eines ganzen Objekts. Beispieldaten sind erfunden, keine echten Namen.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- der zweite Test eine ablehnende Regel ohne Datenbank prüft und grün ist,
- zwei Stellen mit Datei und Zeile verkleinert sind und der Gewinn benannt ist,
- beide Konfigurationen über die Umgebungsvariable laufen und die Fachlogik nachweislich unverändert ist.
Wie unter Allgemein.
MandalorianPlus Aufgabe
Abschnitt betitelt „MandalorianPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Ordne drei Stellen eures Projekts (oder des verwendeten Frameworks) ein: Ist es DIP, Dependency Injection, beides, keines, oder arbeitet ein IoC-Container? Begründe jede Einordnung in einem Satz mit den zwei getrennten Fragen: Wird die Abhängigkeit hereingereicht, und ist das Hereingereichte eine Abstraktion?
- Erkläre im Design-Review in drei bis fünf Sätzen, wie die fünf SOLID-Prinzipien in euren Umbauten aus Aufgabe 08 und 09 zusammengewirkt haben: Welche Entscheidung hat welche andere erst möglich gemacht?
- Beurteile in drei Sätzen, ob euer Projekt einen IoC-Container bräuchte oder die Verdrahtung von Hand reicht, und nenne den Auslöser, bei dem du deine Meinung änderst.
Tipp: Kapitel 14 beschreibt die Kette SRP → OCP, LSP → OCP, ISP → DIP und DIP als Klammer. Belege jeden Zusammenhang mit einer Stelle aus eurem Code.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- die drei Stellen mit beiden Fragen richtig eingeordnet sind,
- die Erklärung mindestens drei Zusammenhänge zwischen Prinzipien an Stellen des eigenen Codes belegt,
- die Beurteilung des Containers ein Kriterium und einen Auslöser für einen Meinungswechsel nennt.
Wie unter Allgemein.
Zeit dafür
Abschnitt betitelt „Zeit dafür“Durchschnittlich bis Wesentlich_vollständig: ca. 70 min (5 min Board-Check, 10 min Kata, 25 min Review und Retrospektive, 30 min Release und Repository-Umbau)
Autoren
Abschnitt betitelt „Autoren“GAM
CC-BY-SA