Übung »Wiederholung ST2«

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

Dauer
Ca. 480 min

Inhalt

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.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap. 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:

Sie sollen folgendes tun:

Die nachfolgenden Aufgaben leiten Sie durch den Prozess. Für jeden Zwischenschritt gibt es jeweils ein Repo mit Beispiellösungen dafür.

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:

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

Lösung

Eine Beispiel-Lösung finden Sie im Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-e1. Das Repo ist noch nicht sofort für Sie 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 Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-e2. (Wird auch erst im Laufe der Übung sichtbar geschaltet.)

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

Lösung

Eine Beispiel-Lösung finden Sie im Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-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 Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-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

Eine Beispiel-Lösung für die Schritte 3-5 finden Sie im Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-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.

(Hier sind die Lösungen schon 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

Eine Beispiel-Lösung für die Schritte 2 und 3 finden Sie im Repo https://git.st.archi-lab.io/students/exercise-projects/semester-recap/st2-recap-solution-e6.

Es sind nur die REST-Endpoints für Customer implementiert. Invoice und Voucher gehen dann analog, das habe ich aus Zeitgründen wegelassen. Für die Endpoints ist eine zusätzliche Testklasse (CustomerRESTTests) implementiert.