Architektur- und Entwurfsmuster

Pattern nicht als Theorie, sondern mit Zweck, Einsatzort und Warnsignal.

Enterprise JavaBeispieleArchitekturOffline HTML

Wichtige Muster im Beispielprojekt

PatternZweckEinsatzortWarnsignal
Aggregate RootKonsistenz innerhalb einer fachlichen Grenze schützenOrder verwaltet Lines und StatusAndere Klassen ändern interne Listen direkt
RepositoryPersistenz hinter fachlichem Port versteckenOrderRepositoryDomain hängt an EntityManager
Application ServiceUse Case orchestrierenPlaceOrderUseCaseController enthält Geschäftslogik
Ports & AdaptersFrameworks austauschbar haltenDomain/Application vs REST/JPA/KafkaAdapter rufen andere Adapter direkt auf
FactoryKonsistente Erzeugung komplexer ObjekteOrderFactorynew über den ganzen Code verstreut
StrategyAustauschbare FachvariantePricingPolicyif/else-Ketten für Preislogik
Policy ObjectAutorisierung/Fachregel testbar kapselnCustomerAccessPolicySecurity-Regeln in Controller verstreut
OutboxDB-Commit und Event zuverlässig verbindenOutboxMessageEvent nach Commit geht verloren
Anti-Corruption LayerFremde Modelle fernhaltenSOAP Partner GatewayWSDL-Klassen in Domain

Monster-Methode refactoren

Viele Legacy-Systeme enthalten Methoden, die Validierung, Mapping, DB-Zugriff, SOAP-Aufruf, Statusänderung, Logging und Fehlerbehandlung mischen. Refactoring beginnt nicht mit „alles neu“, sondern mit sichtbaren Schnitten.

Refactoring-Ziel: Use Case als lesbare Geschichte
public InvoiceId createInvoice(CreateInvoiceRequest request) {
    validate(request);
    OrderSnapshot order = orderGateway.load(request.orderId());
    Invoice invoice = invoiceFactory.from(order);
    invoiceRepository.save(invoice);
    outbox.append(InvoiceCreated.from(invoice));
    return invoice.id();
}
Prüffrage: Kann ein Fachkollege den Ablauf der Methode erklären, ohne SQL, HTTP oder Frameworkdetails verstehen zu müssen?

Entscheidungsregeln

FrageWenn jaWenn nein
Ist die Regel fachlich stabil?In Domain/Policy modellierenIn Application/Adapter lassen
Ist die Abhängigkeit extern?Port definieren und Adapter bauenDirekter Aufruf kann ok sein
Muss es transaktional konsistent sein?Use-Case-Grenze festlegenAsynchrones Event prüfen
Muss ein Consumer später replayen?Event-Versionierung und Idempotenz planenCommand/Request genügt vielleicht
Muss es unabhängig deploybar sein?API/Event-Vertrag hart pflegenModularer Monolith kann reichen
⌂ Cockpit