Kontakt
stefan.bente[at]th-koeln.de
+49 2261 8196 6367
Discord Server
Prof. Bente Personal Zoom
Adresse
Steinmüllerallee 4
51643 Gummersbach
Gebäude LC4
Raum 1708 (Wegbeschreibung)
Sprechstunde nach Vereinbarung
Terminanfrage: calendly.com Wenn Sie dieses Tool nicht nutzen wollen, schicken Sie eine Mail und ich weise Ihnen einen Termin zu.

Übung »Wiederholung ST2«

Diese Übung enthält in einem kompakten Beispiel den gesamten Stoff von ST2.

Dauer
Ca. 480 min

Worum geht es?

In dieser Übung wiederholen Sie anhand eines knappen, kompakten Beispiels den gesamten Stoff von ST2. Die Beispiel-Anwendung finden Sie in dem Repo https://git.archi-lab.io/public-repos/st2-recap/st2-recap-assignment. Bitte clonen Sie das. Das Repo hat auch ein paar einfache Unit-Tests (in der Klasse AllTests). Bitte denken Sie daran, auch diese Klasse mit zu pflegen, wenn Sie den Code ändern.

Ihre Aufgabe

Es ist ein kleines Beispiel (4 Klassen, 200 Zeilen Code insgesamt). Es geht um folgendes:

  • Wir betrachten das Payment-Modul eines Webshops. Der Shop operiert in Deutschland, NL, Belgien, Österreich, Dänemark und Schweden. Er unterstützt also die Währungen EUR, DKR und SEK.
  • Es gibt Kunden, die Rechnungen (Invoice) bekommen, für bestellte Waren. Kunden haben nur Vor- und Nachname sowie eine Email. Es gibt noch Firmenkunden, die nur einen Namen und eine Email haben.
  • Umtausch auf Kulanz wird durch die Ausgabe von Gutscheinen (Voucher) geregelt. Diese sind personalisiert. Man kann Bestellungen mit solchen Vouchers bezahlen. Man kann die Vouchers auch mehrmals einsetzen, so lange, bis der Geldbetrag darauf verbraucht ist.

Sie sollen folgendes tun:

  • Wenden Sie Clean-Code-Regeln und die SOLID-Prinzipien an, und machen Sie ein entsprechendes Refactoring.
  • Implementieren Sie Domain Primitives.
  • Identifizieren Sie Entities, Value Objects und Aggregates.
  • Implementieren Sie dies mit JPA.
  • Spezifizieren Sie ein REST-API.
  • Implementieren Sie das REST-API.

Die nachfolgenden Aufgaben leiten Sie durch den Prozess.

Lösungen

Für die Zwischenschritte gibt es in den meisten Fällen Beispiellösungen. Die Lösungen finden Sie alle im Repo https://git.archi-lab.io/public-repos/st2-recap/st2-recap-solution. Unten sind Deep Links auf dieses Repo, die Sie direkt zu den Lösungen führen.

E1) Clean Code & SOLID - Analyse der Probleme

In den Code sind absichtlich Verstöße gegen Clean-Code-Regeln und SOLID-Prinzipien eingebaut, und zwar (mindestens …) die folgenden:

  • Clean Code
    • Meaningful names
    • Keep your methods small
    • Proper error handling
  • SOLID
    • Single Responsibility Principle
    • Open-Closed Principle
    • Liskov Substitution Principle

Nehmen Sie sich ein bisschen Zeit, um den Code zu verstehen und zu analysieren. Wenn Ihnen die obigen Regeln und Prinzipien nichts mehr sagen, dann schauen Sie nochmal in die Videos oder die zugehörigen Scripte. Dann annotieren Sie bitte alle Verstöße, die Sie finden, mit TODO im Code, und schreiben Sie dazu, was Sie refactorn würden.

Beispiel 1:

// TODO CC - meaningful names
// "dob" ist kein sprechender Name, sondern eine unverständliche Abkürzung. 
// Ich würde das Attribut zu "dateOfBirth" umbenennen.

Beispiel 2:

// TODO SOLID - open-closed-principle
// Das Attribut "isValid" ist zwar private, aber es hat einen Setter. Damit kann man die 
// Gültigkeit des Objektzustands einfach so von außen setzen! Das sollte nicht sein. 
// Ich würde das Attribut ganz entfernen, natürlich auch den Setter, und die "Gültigkeit" 
// dann aus den anderen Objekt-Attributen berechnen.

Insgesamt kommen (wie schon oben gelistet) mindestens die folgenden Verstöße vor - jedes dieser Todos sollten Sie also mindestens einmal verwenden.

// TODO CC - meaningful names
// TODO CC - keep your methods small
// TODO CC - proper error handling
// TODO SOLID - single-responsibility-principle
// TODO SOLID - open-closed-principle
// TODO SOLID - liskov-substitution-principle

Tipps

  • Obwohl der Code kurz ist, liegt doch viel im Argen :-(. Am einfachsten ist es, die verschiedenen Verstöße nacheinander abzuarbeiten. Also erst alle Verstöße gegen “Meaningful Names”, dann die gegen “Keep your methods small”, etc.
  • Manchmal verstoßen Codestellen auch gegen mehrere Regeln/Prinzipien auf einmal!
  • Die Beispiel-Lösung kommt auf insgesamt 43 Todos aus Verstößen gegen Clean Code und SOLID. Die Zahl ist nicht in Stein gemeißelt - hängt ja ein bisschen davon ab, was man wie oft wo anmerkt. Aber vielleicht hilft das als Orientierung.
  • Wichtig: Refactorn Sie noch nichts! Das kommt in den nächsten Schritten.

Lösung

Eine Beispiel-Lösung finden Sie im Lösungs-Repo in Folder E1. Das Repo ist (möglicherweise) noch nicht sofort sichtbar, sondern wird erst im Laufe der Übung sichtbar geschaltet.

E2) Refactoring der Verstöße gegen “Meaningful Names”

Machen Sie jetzt als erstes einmal ein Refactoring der Benennung von Variablen und ggfs. Klassen, damit der Code ein bisschen übersichtlicher wird. Am besten löschen Sie dann jeweils das Todo aus Ihrem Code. Tipp:
Wenn Sie IntelliJ verwenden, dann gibt es links in der Fußzeile den Button “TODO”, der alle Todos im gesamten Code listet. Damit können Sie die Todos prima filtern.

TODO-Liste

Lösung

Eine Beispiel-Lösung finden Sie im Lösungs-Repo in Folder E2.

E3) Domain Primitives

Als nächsten Schritt im Refactoring empfehle ich die Domain Primitives. Mit diesen Domain Primitives löst man nämlich auch eine ganze Anzahl von SOLID-Verstößen (“Single Responsibility” und “Open-Closed Principle”) auf. Man kann im Code mindestens drei Domain Primitives finden. Implementieren Sie diese und sorgen Sie für ein entsprechendes Refactoring im Code.

Tipps

  • Lassen Sie die restlichen CC- und SOLID-Verstöße (die nicht über Domain Primitives zu lösen sind) erst einmal in Ruhe - es ist nicht gut, wenn man zu viel auf einmal ändert.
  • Die eine Ausnahme hiervon ist Invoice.payPerVoucher(...) - diese Methode sollten Sie unbedingt direkt mit refactorn, weil man sonst das Potential der DPs nicht ausnutzt. Also: Verschieben Sie direkt auch Funktionalität hin zu Voucher, um dort einen Betrag abzubuchen.
  • Achten Sie darauf, dass die Tests grün bleiben! Sie müssen mit den DPs auch in AllTests einiges ändern. (Dass bestehende Unittests grün bleiben, ist im Übrigen ja genau die “Essenz” eines professionellen, also gut abgesicherten Refactorings.)
  • Nach der Einführung der DPs bleiben in der Beispiellösung noch 12 Todos übrig - nur so als Orientierung.

Lösung

Eine Beispiel-Lösung finden Sie im Lösungs-Repo in Folder E3.

E4) Auflösen der verbleibenden Clean-Code- und SOLID-Verstöße durch geeignetes Refactoring

Bringen Sie jetzt das Refactoring zu Ende, indem Sie die verbleibenden Verstöße im Code beheben.

Lösung

Eine Beispiel-Lösung finden Sie im Lösungs-Repo in Folder E4.

E5) Identifizieren Sie Aggregates, legen Sie Package-Strukturen an, und persistieren Sie alles mit JPA

  1. Erstellen Sie als Erstes ein logisches Datenmodell, in dem Sie Entities und Domain Primitives (als Value Objects) erfassen. Attribute brauchen nicht dargestellt zu werden, Domain Primitives / VOs sollten als eigene Klassen abgebildet werden.
  2. Ordnen Sie alles zu Aggregates an, indem Sie im Datenmodell die Aggregates umkringeln. Wie viele Aggregates gibts es?
  3. Legen Sie gemäß der Konvention, die wir im Praktikum verwendet haben, Packages entlang der Aggregate-Grenzen an. Ergänzen Sie Klassen, die Sie für eine Persistierung mit JPA brauchen, und machen Sie an den richtigen Stellen die JPA-Annotationen für Entities und Value Objects.
  4. Legen Sie für jedes Aggregate auch schon mal einen Application Service an, auch wenn der vielleicht noch leer ist. Schauen Sie, dass der Application Service im richtigen Sub-Package landet.
  5. Stellen Sie die Testklasse so um, dass die Objekte auch wirklich persistiert werden.

Lösung

Schritt 1 und 2 sieht man in diesem logischen Datenmodell:

Lösung E5

E6) Spezifizieren und implementieren Sie REST-Endpoints

  1. Spezifizieren Sie die in der nachfolgenden Tabelle genannten REST-Endpoints.
  2. Implementieren Sie die REST-Endpoints. Achten Sie darauf, dass Sie DTOs bereitstellen und die Geschäftslogik nicht in den Controllern anlegen, sondern in ApplicationServices und in Domänenklassen.
  3. Schreiben Sie je einen Unittest für jeden REST-Endpoint. Orientieren Sie sich dafür an den Testklassen aus dem REST-Meilenstein M4 des Praktikums.
Aufgabe Verb Endpoint
Lege Kunde neu an    
Hole Liste aller Kunden    
Zeige einen Kunden an    
Ändere die Email eines Kunden    
Lösche einen Kunden    
Finde alle Kunden mit einem bestimmten Nachname    
Lege eine Rechnung neu an    
Zeige eine bestimmte Rechnung an    
Suche alle Rechnungen für einen Kunden    
Lösche eine Rechnung    
Lege einen Voucher neu an    
Finde Vouchers, die für einen bestimmten Zweck eingelöst wurden    
Finde alle Vouchers einer Währung und >0 Geld drauf für einen Kunden    

Lösung

Hier sind die Lösungen jetzt mit in der Tabelle.

Aufgabe Verb Endpoint
Lege Kunde neu an POST /customers
Hole Liste aller Kunden GET /customers
Zeige einen Kunden an GET /customers/{c-id}
Ändere die Email eines Kunden PATCH /customers/{c-id}
Lösche einen Kunden DELETE /customers/{c-id}
Finde alle Kunden mit einem bestimmten Nachname GET /customers?lastName={lastNameString}
Lege eine Rechnung neu an POST /invoices
Zeige eine bestimmte Rechnung an GET /invoices/{i-id}
Suche alle Rechnungen für einen Kunden GET /invoices?customerId={c-id}
Lösche eine Rechnung DELETE /invoices/{i-id}
Lege einen Voucher neu an POST /vouchers
Finde Vouchers, die für einen bestimmten Zweck eingelöst wurden GET /vouchers?purpose={purposeString}
Finde alle Vouchers einer Währung und >0 Geld drauf für einen Kunden GET /vouchers?customerId={c-id}&currency={currencyString}&amountIsGreaterThan=0

Das ist aus Zeitgründen im Lösungsrepo noch nicht implementiert (vielleicht später mal).