Enterprise Maven Master

Master 24 - Übungsaufgaben

Fünf Aufgaben zum Selbstausprobieren, jede an echten Klassen des Workspace mvn-ws-acl-strangler-deep-dive. Keine Lösungsdateien - die Aufgaben werden direkt im jeweiligen Submodul bearbeitet und über mvn test verifiziert.

Aufgabe 1 - Eine echte Charakterisierung schreiben

Ausgangspunkt: characterization-tests/.../GoldenMasterCharacterizationTest.java

Beobachtung: Die bestehenden Golden-Master-Tests bauen ein LegacyWorkflowResult von Hand zusammen und vergleichen nur dessen Serialisierung - sie rufen keine der echten Monster-Beans (OrderProcessingMonsterBean, BillingRunMonsterBean, ...) auf. Das ist eigentlich ein Bruch mit dem Grundprinzip von Characterization Testing: man friert das Verhalten des echten Codes ein, nicht eine Nacherzählung davon.

Aufgabe: Schreibe einen neuen Test, der ReturnsAndRefundMonsterBean (bislang nicht Teil der Golden Master) direkt instanziiert - orientiere dich an den Mock-Setups aus ReturnsAndRefundMonsterBeanTest.java im Modul enterprise-legacy-monolith - und dessen echtes Ergebnis in eine neue Golden-Datei /golden/returns-refund.txt schreibst.

Hinweis

Lauf zuerst mit einem absichtlich falschen Erwartungswert, lies den tatsächlichen canonicalSnapshot()-Output aus der Testausgabe und übernimm ihn 1:1 als Golden File - so entsteht ein echter Snapshot statt einer Vermutung.

Erfolgskriterium: mvn -pl characterization-tests -am test ist grün, und die neue Golden-Datei enthält Werte, die tatsächlich aus der Bean-Ausführung stammen, nicht von Hand erfunden sind.

Aufgabe 2 - Einen Bug provozieren und beobachten, was ihn fängt

Ausgangspunkt: enterprise-legacy-monolith/.../BillingRunMonsterBean.java

Hintergrund: Bei der Laufzeit-Verifikation dieses Moduls wurden zwei falsche Testerwartungswerte gefunden, weil mvn test tatsächlich ausgeführt wurde (siehe Änderungen). Diese Aufgabe dreht die Erfahrung um: du baust bewusst einen kleinen Fehler ein und beobachtest das Sicherheitsnetz in Aktion.

Aufgabe: Ändere in BillingRunMonsterBean eine Konstante oder einen Rechenschritt (z. B. den Steuersatz oder die Rundung in der Summenbildung) geringfügig. Führe danach mvn -pl enterprise-legacy-monolith,characterization-tests -am test aus.

Hinweis

Beobachte genau, welcher Test zuerst rot wird - der spezifische BillingRunMonsterBeanTest oder der allgemeinere Golden-Master-Test? Das zeigt, welche Testebene welche Art von Regression tatsächlich abdeckt. Mach die Änderung danach wieder rückgängig (git checkout -- enterprise-legacy-monolith).

Erfolgskriterium: Du kannst in einem Satz erklären, welcher Test die Änderung erkannt hat und warum die anderen sie nicht erkannt hätten.

Aufgabe 3 - Migrationsfortschritt je Namespace trennen

Ausgangspunkt: strangler-router/.../MigrationProgress.java

Beobachtung: RoutingPolicy unterstützt bereits Prozent-Rollout, Shadow-Modus und Fallback, und MigrationProgress zählt die Ergebnisse eines Namespaces (z. B. "order-booking") und verweigert nach complete() jedes weitere Legacy-Ergebnis. Was fehlt: mehrere Migrationen laufen in der Praxis parallel (order-booking, billing, returns, ...), aber es gibt noch keine Stelle, die mehrere MigrationProgress-Instanzen verwaltet.

Aufgabe: Baue eine MigrationProgressRegistry, die pro Namespace genau eine MigrationProgress-Instanz vorhält (Lazy-Erzeugung beim ersten Zugriff) und eine Methode overallMigratedPercentage() anbietet, die den gewichteten Durchschnitt über alle bekannten Namespaces liefert.

Hinweis

"Gewichtet" heißt: ein Namespace mit 10.000 Aufrufen soll das Gesamtbild stärker beeinflussen als einer mit 10 Aufrufen - nicht einfach die Prozentsätze mitteln.

Erfolgskriterium: Ein neuer Test zeigt zwei Namespaces mit unterschiedlichem Fortschritt und unterschiedlichem Volumen, bei denen overallMigratedPercentage() erkennbar zum volumenstärkeren Namespace tendiert.

Aufgabe 4 - Vergleichslauf automatisch schließen

Ausgangspunkt: parallel-run-comparison/.../ComparisonRun.java

Beobachtung: ComparisonEngine hat bereits eine Toleranzschwelle für numerische Felder, und ComparisonRun sammelt mehrere Batches über eine ganze Vergleichs-Session und friert das Ergebnis mit close() ein. Was fehlt: close() muss aktuell von außen aufgerufen werden - es gibt keine Regel, wann ein Lauf sich selbst als überfällig betrachtet.

Aufgabe: Erweitere ComparisonRun um ein Zeitlimit (z. B. Duration maxAge ab Erzeugung). Ein Versuch, nach Ablauf noch record(...) aufzurufen, soll denselben Fehler werfen wie ein bereits geschlossener Lauf - der Lauf ist dann faktisch geschlossen, auch ohne expliziten close()-Aufruf.

Hinweis

Ein injizierbarer Clock statt Instant.now() macht die Zeitprüfung deterministisch testbar, ohne in echten Tests warten zu müssen.

Erfolgskriterium: Ein neuer Test mit einer manuell vorgestellten Clock zeigt, dass record(...) nach Ablauf der Frist eine ComparisonRunClosedException wirft, ohne dass close() explizit aufgerufen wurde.

Aufgabe 5 - Neuen ACL-Fehlerfall abbilden

Ausgangspunkt: anti-corruption-layer/.../LegacyErrorTranslator.java

Aufgabe: Suche in enterprise-legacy-monolith nach einem Legacy-Fehlercode oder -Zustand, der aktuell noch nicht in LegacyErrorTranslator auf ein modernes Fehlerobjekt abgebildet wird (z. B. ein Ablehnungs- oder Timeout-Fall aus LegacyJmsRequestReply oder den SOAP-Clients), und ergänze die passende Übersetzung.

Hinweis

Die Anti-Corruption-Layer soll verhindern, dass Legacy-Fehlerkonzepte 1:1 nach außen dringen - überlege, wie sich ein technischer Legacy-Fehler (Timeout, Ablehnung) in ein fachlich sinnvolles, modernes Fehlerobjekt übersetzt.

Erfolgskriterium: Ein neuer Test in AclContractTest.java zeigt Ein- und Ausgabe der neuen Übersetzung.

Einordnung

Diese Aufgaben sind bewusst offen gehalten - es gibt keine hinterlegte Musterlösung. Der Lernwert liegt darin, echten, ungeschönten Legacy-Code zu lesen, eine eigene Entscheidung zu treffen und sie über mvn test gegen das bestehende Sicherheitsnetz zu prüfen - genau der Arbeitsmodus, den Master 24 als Ganzes vermittelt.

⌂ Cockpit