Große Sammlung Enterprise-Entwurfsmuster

120 konkrete Muster-Einträge: GoF, Enterprise, Integration, DDD, Resilience, Security, Persistenz und Testing.

Enterprise Entwurfsmuster Landkarte
0 Treffer
Erzeugungsmuster (Creational Patterns)

Objekterzeugung, Variantenbildung, Konfiguration und kontrollierte Instanzierung.

Erzeugungsmuster

dp001: Factory Method im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Factory Method
Priorität: 9/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Factory Method wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Factory Method - kapselt Erzeugung und Variantenbildung.
public final class FactoryMethodCustomerFactory {
    public CustomerHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardCustomerHandler();
            case "PARTNER" -> new PartnerCustomerHandler();
            default -> throw new IllegalArgumentException("Unsupported customer type: " + type);
        };
    }
}

interface CustomerHandler { void process(CustomerRequest request); }
final class StandardCustomerHandler implements CustomerHandler { public void process(CustomerRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerCustomerHandler implements CustomerHandler { public void process(CustomerRequest r) { /* valide Partner-Verarbeitung */ } }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp002: Abstract Factory im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Abstract Factory
Priorität: 9/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Abstract Factory wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Abstract Factory - kapselt Erzeugung und Variantenbildung.
public final class AbstractFactoryPaymentFactory {
    public PaymentHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardPaymentHandler();
            case "PARTNER" -> new PartnerPaymentHandler();
            default -> throw new IllegalArgumentException("Unsupported payment type: " + type);
        };
    }
}

interface PaymentHandler { void process(PaymentRequest request); }
final class StandardPaymentHandler implements PaymentHandler { public void process(PaymentRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerPaymentHandler implements PaymentHandler { public void process(PaymentRequest r) { /* valide Partner-Verarbeitung */ } }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp003: Builder im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Builder
Priorität: 9/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Builder wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Builder - kapselt Erzeugung und Variantenbildung.
public final class BuilderPartnerFactory {
    public PartnerHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardPartnerHandler();
            case "PARTNER" -> new PartnerPartnerHandler();
            default -> throw new IllegalArgumentException("Unsupported partner type: " + type);
        };
    }
}

interface PartnerHandler { void process(PartnerRequest request); }
final class StandardPartnerHandler implements PartnerHandler { public void process(PartnerRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerPartnerHandler implements PartnerHandler { public void process(PartnerRequest r) { /* valide Partner-Verarbeitung */ } }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp004: Prototype im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Prototype
Priorität: 9/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Prototype wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Prototype - kapselt Erzeugung und Variantenbildung.
public final class PrototypeAccountFactory {
    public AccountHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardAccountHandler();
            case "PARTNER" -> new PartnerAccountHandler();
            default -> throw new IllegalArgumentException("Unsupported account type: " + type);
        };
    }
}

interface AccountHandler { void process(AccountRequest request); }
final class StandardAccountHandler implements AccountHandler { public void process(AccountRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerAccountHandler implements AccountHandler { public void process(AccountRequest r) { /* valide Partner-Verarbeitung */ } }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp005: Singleton im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Singleton
Priorität: 9/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Singleton wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Singleton - kapselt Erzeugung und Variantenbildung.
public final class SingletonProductFactory {
    public ProductHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardProductHandler();
            case "PARTNER" -> new PartnerProductHandler();
            default -> throw new IllegalArgumentException("Unsupported product type: " + type);
        };
    }
}

interface ProductHandler { void process(ProductRequest request); }
final class StandardProductHandler implements ProductHandler { public void process(ProductRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerProductHandler implements ProductHandler { public void process(ProductRequest r) { /* valide Partner-Verarbeitung */ } }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp006: Dependency Injection im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Dependency Injection
Priorität: 8/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Dependency Injection wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Dependency Injection - kapselt Erzeugung und Variantenbildung.
public final class DependencyInjectionOrderFactory {
    public OrderHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardOrderHandler();
            case "PARTNER" -> new PartnerOrderHandler();
            default -> throw new IllegalArgumentException("Unsupported order type: " + type);
        };
    }
}

interface OrderHandler { void process(OrderRequest request); }
final class StandardOrderHandler implements OrderHandler { public void process(OrderRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerOrderHandler implements OrderHandler { public void process(OrderRequest r) { /* valide Partner-Verarbeitung */ } }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp007: Object Mother im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Object Mother
Priorität: 8/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Object Mother wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Object Mother - kapselt Erzeugung und Variantenbildung.
public final class ObjectMotherCustomerFactory {
    public CustomerHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardCustomerHandler();
            case "PARTNER" -> new PartnerCustomerHandler();
            default -> throw new IllegalArgumentException("Unsupported customer type: " + type);
        };
    }
}

interface CustomerHandler { void process(CustomerRequest request); }
final class StandardCustomerHandler implements CustomerHandler { public void process(CustomerRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerCustomerHandler implements CustomerHandler { public void process(CustomerRequest r) { /* valide Partner-Verarbeitung */ } }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp008: Test Data Builder im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Test Data Builder
Priorität: 8/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Test Data Builder wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Test Data Builder - kapselt Erzeugung und Variantenbildung.
public final class TestDataBuilderPaymentFactory {
    public PaymentHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardPaymentHandler();
            case "PARTNER" -> new PartnerPaymentHandler();
            default -> throw new IllegalArgumentException("Unsupported payment type: " + type);
        };
    }
}

interface PaymentHandler { void process(PaymentRequest request); }
final class StandardPaymentHandler implements PaymentHandler { public void process(PaymentRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerPaymentHandler implements PaymentHandler { public void process(PaymentRequest r) { /* valide Partner-Verarbeitung */ } }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp009: Static Factory im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Static Factory
Priorität: 8/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Static Factory wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Static Factory - kapselt Erzeugung und Variantenbildung.
public final class StaticFactoryPartnerFactory {
    public PartnerHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardPartnerHandler();
            case "PARTNER" -> new PartnerPartnerHandler();
            default -> throw new IllegalArgumentException("Unsupported partner type: " + type);
        };
    }
}

interface PartnerHandler { void process(PartnerRequest request); }
final class StandardPartnerHandler implements PartnerHandler { public void process(PartnerRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerPartnerHandler implements PartnerHandler { public void process(PartnerRequest r) { /* valide Partner-Verarbeitung */ } }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp010: Fluent Builder im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Fluent Builder
Priorität: 7/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Fluent Builder wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Fluent Builder - kapselt Erzeugung und Variantenbildung.
public final class FluentBuilderAccountFactory {
    public AccountHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardAccountHandler();
            case "PARTNER" -> new PartnerAccountHandler();
            default -> throw new IllegalArgumentException("Unsupported account type: " + type);
        };
    }
}

interface AccountHandler { void process(AccountRequest request); }
final class StandardAccountHandler implements AccountHandler { public void process(AccountRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerAccountHandler implements AccountHandler { public void process(AccountRequest r) { /* valide Partner-Verarbeitung */ } }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp011: Configuration Factory im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Configuration Factory
Priorität: 7/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Configuration Factory wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Configuration Factory - kapselt Erzeugung und Variantenbildung.
public final class ConfigurationFactoryProductFactory {
    public ProductHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardProductHandler();
            case "PARTNER" -> new PartnerProductHandler();
            default -> throw new IllegalArgumentException("Unsupported product type: " + type);
        };
    }
}

interface ProductHandler { void process(ProductRequest request); }
final class StandardProductHandler implements ProductHandler { public void process(ProductRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerProductHandler implements ProductHandler { public void process(ProductRequest r) { /* valide Partner-Verarbeitung */ } }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp012: Service Factory im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Service Factory
Priorität: 7/10
Kategorie: Erzeugungsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Service Factory wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Service Factory - kapselt Erzeugung und Variantenbildung.
public final class ServiceFactoryOrderFactory {
    public OrderHandler create(String type) {
        return switch (type) {
            case "STANDARD" -> new StandardOrderHandler();
            case "PARTNER" -> new PartnerOrderHandler();
            default -> throw new IllegalArgumentException("Unsupported order type: " + type);
        };
    }
}

interface OrderHandler { void process(OrderRequest request); }
final class StandardOrderHandler implements OrderHandler { public void process(OrderRequest r) { /* valide Standard-Verarbeitung */ } }
final class PartnerOrderHandler implements OrderHandler { public void process(OrderRequest r) { /* valide Partner-Verarbeitung */ } }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Strukturmuster (Structural Patterns)

Bausteine verbinden, Legacy kapseln, APIs stabilisieren und technische Komplexität verstecken.

Strukturmuster

dp013: Adapter im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Adapter
Priorität: 9/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Adapter wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Adapter - trennt interne Domain von externer Schnittstelle.
public final class AdapterCustomerAdapter {
    private final ExternalCustomerClient client;
    public AdapterCustomerAdapter(ExternalCustomerClient client) { this.client = client; }

    public CustomerResult submit(CustomerRequest request) {
        ExternalCustomerPayload payload = new ExternalCustomerPayload(request.id(), request.amount().toPlainString());
        ExternalCustomerResponse response = client.send(payload);
        return new CustomerResult(response.reference(), response.accepted());
    }
}

interface ExternalCustomerClient { ExternalCustomerResponse send(ExternalCustomerPayload payload); }
record ExternalCustomerPayload(String id, String amount) { }
record ExternalCustomerResponse(String reference, boolean accepted) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp014: Facade im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Facade
Priorität: 9/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Facade wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Facade - trennt interne Domain von externer Schnittstelle.
public final class FacadePaymentAdapter {
    private final ExternalPaymentClient client;
    public FacadePaymentAdapter(ExternalPaymentClient client) { this.client = client; }

    public PaymentResult submit(PaymentRequest request) {
        ExternalPaymentPayload payload = new ExternalPaymentPayload(request.id(), request.amount().toPlainString());
        ExternalPaymentResponse response = client.send(payload);
        return new PaymentResult(response.reference(), response.accepted());
    }
}

interface ExternalPaymentClient { ExternalPaymentResponse send(ExternalPaymentPayload payload); }
record ExternalPaymentPayload(String id, String amount) { }
record ExternalPaymentResponse(String reference, boolean accepted) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp015: Decorator im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Decorator
Priorität: 9/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Decorator wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Decorator - trennt interne Domain von externer Schnittstelle.
public final class DecoratorPartnerAdapter {
    private final ExternalPartnerClient client;
    public DecoratorPartnerAdapter(ExternalPartnerClient client) { this.client = client; }

    public PartnerResult submit(PartnerRequest request) {
        ExternalPartnerPayload payload = new ExternalPartnerPayload(request.id(), request.amount().toPlainString());
        ExternalPartnerResponse response = client.send(payload);
        return new PartnerResult(response.reference(), response.accepted());
    }
}

interface ExternalPartnerClient { ExternalPartnerResponse send(ExternalPartnerPayload payload); }
record ExternalPartnerPayload(String id, String amount) { }
record ExternalPartnerResponse(String reference, boolean accepted) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp016: Proxy im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Proxy
Priorität: 9/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Proxy wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Proxy - trennt interne Domain von externer Schnittstelle.
public final class ProxyAccountAdapter {
    private final ExternalAccountClient client;
    public ProxyAccountAdapter(ExternalAccountClient client) { this.client = client; }

    public AccountResult submit(AccountRequest request) {
        ExternalAccountPayload payload = new ExternalAccountPayload(request.id(), request.amount().toPlainString());
        ExternalAccountResponse response = client.send(payload);
        return new AccountResult(response.reference(), response.accepted());
    }
}

interface ExternalAccountClient { ExternalAccountResponse send(ExternalAccountPayload payload); }
record ExternalAccountPayload(String id, String amount) { }
record ExternalAccountResponse(String reference, boolean accepted) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp017: Composite im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Composite
Priorität: 9/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Composite wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Composite - trennt interne Domain von externer Schnittstelle.
public final class CompositeProductAdapter {
    private final ExternalProductClient client;
    public CompositeProductAdapter(ExternalProductClient client) { this.client = client; }

    public ProductResult submit(ProductRequest request) {
        ExternalProductPayload payload = new ExternalProductPayload(request.id(), request.amount().toPlainString());
        ExternalProductResponse response = client.send(payload);
        return new ProductResult(response.reference(), response.accepted());
    }
}

interface ExternalProductClient { ExternalProductResponse send(ExternalProductPayload payload); }
record ExternalProductPayload(String id, String amount) { }
record ExternalProductResponse(String reference, boolean accepted) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp018: Bridge im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Bridge
Priorität: 8/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Bridge wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Bridge - trennt interne Domain von externer Schnittstelle.
public final class BridgeOrderAdapter {
    private final ExternalOrderClient client;
    public BridgeOrderAdapter(ExternalOrderClient client) { this.client = client; }

    public OrderResult submit(OrderRequest request) {
        ExternalOrderPayload payload = new ExternalOrderPayload(request.id(), request.amount().toPlainString());
        ExternalOrderResponse response = client.send(payload);
        return new OrderResult(response.reference(), response.accepted());
    }
}

interface ExternalOrderClient { ExternalOrderResponse send(ExternalOrderPayload payload); }
record ExternalOrderPayload(String id, String amount) { }
record ExternalOrderResponse(String reference, boolean accepted) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp019: Flyweight im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Flyweight
Priorität: 8/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Flyweight wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Flyweight - trennt interne Domain von externer Schnittstelle.
public final class FlyweightCustomerAdapter {
    private final ExternalCustomerClient client;
    public FlyweightCustomerAdapter(ExternalCustomerClient client) { this.client = client; }

    public CustomerResult submit(CustomerRequest request) {
        ExternalCustomerPayload payload = new ExternalCustomerPayload(request.id(), request.amount().toPlainString());
        ExternalCustomerResponse response = client.send(payload);
        return new CustomerResult(response.reference(), response.accepted());
    }
}

interface ExternalCustomerClient { ExternalCustomerResponse send(ExternalCustomerPayload payload); }
record ExternalCustomerPayload(String id, String amount) { }
record ExternalCustomerResponse(String reference, boolean accepted) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp020: Wrapper im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Wrapper
Priorität: 8/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Wrapper wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Wrapper - trennt interne Domain von externer Schnittstelle.
public final class WrapperPaymentAdapter {
    private final ExternalPaymentClient client;
    public WrapperPaymentAdapter(ExternalPaymentClient client) { this.client = client; }

    public PaymentResult submit(PaymentRequest request) {
        ExternalPaymentPayload payload = new ExternalPaymentPayload(request.id(), request.amount().toPlainString());
        ExternalPaymentResponse response = client.send(payload);
        return new PaymentResult(response.reference(), response.accepted());
    }
}

interface ExternalPaymentClient { ExternalPaymentResponse send(ExternalPaymentPayload payload); }
record ExternalPaymentPayload(String id, String amount) { }
record ExternalPaymentResponse(String reference, boolean accepted) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp021: Anti-Corruption Layer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Anti-Corruption Layer
Priorität: 8/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Anti-Corruption Layer wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Anti-Corruption Layer - trennt interne Domain von externer Schnittstelle.
public final class AntiCorruptionLayerPartnerAdapter {
    private final ExternalPartnerClient client;
    public AntiCorruptionLayerPartnerAdapter(ExternalPartnerClient client) { this.client = client; }

    public PartnerResult submit(PartnerRequest request) {
        ExternalPartnerPayload payload = new ExternalPartnerPayload(request.id(), request.amount().toPlainString());
        ExternalPartnerResponse response = client.send(payload);
        return new PartnerResult(response.reference(), response.accepted());
    }
}

interface ExternalPartnerClient { ExternalPartnerResponse send(ExternalPartnerPayload payload); }
record ExternalPartnerPayload(String id, String amount) { }
record ExternalPartnerResponse(String reference, boolean accepted) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp022: Gateway im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Gateway
Priorität: 7/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Gateway wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Gateway - trennt interne Domain von externer Schnittstelle.
public final class GatewayAccountAdapter {
    private final ExternalAccountClient client;
    public GatewayAccountAdapter(ExternalAccountClient client) { this.client = client; }

    public AccountResult submit(AccountRequest request) {
        ExternalAccountPayload payload = new ExternalAccountPayload(request.id(), request.amount().toPlainString());
        ExternalAccountResponse response = client.send(payload);
        return new AccountResult(response.reference(), response.accepted());
    }
}

interface ExternalAccountClient { ExternalAccountResponse send(ExternalAccountPayload payload); }
record ExternalAccountPayload(String id, String amount) { }
record ExternalAccountResponse(String reference, boolean accepted) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp023: Assembler im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Assembler
Priorität: 7/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Assembler wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Assembler - trennt interne Domain von externer Schnittstelle.
public final class AssemblerProductAdapter {
    private final ExternalProductClient client;
    public AssemblerProductAdapter(ExternalProductClient client) { this.client = client; }

    public ProductResult submit(ProductRequest request) {
        ExternalProductPayload payload = new ExternalProductPayload(request.id(), request.amount().toPlainString());
        ExternalProductResponse response = client.send(payload);
        return new ProductResult(response.reference(), response.accepted());
    }
}

interface ExternalProductClient { ExternalProductResponse send(ExternalProductPayload payload); }
record ExternalProductPayload(String id, String amount) { }
record ExternalProductResponse(String reference, boolean accepted) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp024: DTO Mapper im Enterprise-Kontext sauber einsetzen

Englischer Begriff: DTO Mapper
Priorität: 7/10
Kategorie: Strukturmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: DTO Mapper wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: DTO Mapper - trennt interne Domain von externer Schnittstelle.
public final class DtoMapperOrderAdapter {
    private final ExternalOrderClient client;
    public DtoMapperOrderAdapter(ExternalOrderClient client) { this.client = client; }

    public OrderResult submit(OrderRequest request) {
        ExternalOrderPayload payload = new ExternalOrderPayload(request.id(), request.amount().toPlainString());
        ExternalOrderResponse response = client.send(payload);
        return new OrderResult(response.reference(), response.accepted());
    }
}

interface ExternalOrderClient { ExternalOrderResponse send(ExternalOrderPayload payload); }
record ExternalOrderPayload(String id, String amount) { }
record ExternalOrderResponse(String reference, boolean accepted) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Verhaltensmuster (Behavioral Patterns)

Abläufe, Entscheidungen, Events und Verantwortlichkeiten sauber verteilen.

Verhaltensmuster

dp025: Strategy im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Strategy
Priorität: 9/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Strategy wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Strategy - macht fachliche Entscheidungen austauschbar und testbar.
public final class StrategyCustomerPolicy {
    private final java.util.List<CustomerRule> rules;
    public StrategyCustomerPolicy(java.util.List<CustomerRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(CustomerRequest request) {
        for (CustomerRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface CustomerRule { void validate(CustomerRequest request); }
final class PositiveAmountRule implements CustomerRule {
    public void validate(CustomerRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp026: Template Method im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Template Method
Priorität: 9/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Template Method wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Template Method - macht fachliche Entscheidungen austauschbar und testbar.
public final class TemplateMethodPaymentPolicy {
    private final java.util.List<PaymentRule> rules;
    public TemplateMethodPaymentPolicy(java.util.List<PaymentRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(PaymentRequest request) {
        for (PaymentRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface PaymentRule { void validate(PaymentRequest request); }
final class PositiveAmountRule implements PaymentRule {
    public void validate(PaymentRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp027: Command im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Command
Priorität: 9/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Command wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Command - macht fachliche Entscheidungen austauschbar und testbar.
public final class CommandPartnerPolicy {
    private final java.util.List<PartnerRule> rules;
    public CommandPartnerPolicy(java.util.List<PartnerRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(PartnerRequest request) {
        for (PartnerRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface PartnerRule { void validate(PartnerRequest request); }
final class PositiveAmountRule implements PartnerRule {
    public void validate(PartnerRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp028: Chain of Responsibility im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Chain of Responsibility
Priorität: 9/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Chain of Responsibility wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Chain of Responsibility - macht fachliche Entscheidungen austauschbar und testbar.
public final class ChainOfResponsibilityAccountPolicy {
    private final java.util.List<AccountRule> rules;
    public ChainOfResponsibilityAccountPolicy(java.util.List<AccountRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(AccountRequest request) {
        for (AccountRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface AccountRule { void validate(AccountRequest request); }
final class PositiveAmountRule implements AccountRule {
    public void validate(AccountRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp029: Observer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Observer
Priorität: 9/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Observer wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Observer - macht fachliche Entscheidungen austauschbar und testbar.
public final class ObserverProductPolicy {
    private final java.util.List<ProductRule> rules;
    public ObserverProductPolicy(java.util.List<ProductRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(ProductRequest request) {
        for (ProductRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface ProductRule { void validate(ProductRequest request); }
final class PositiveAmountRule implements ProductRule {
    public void validate(ProductRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp030: Mediator im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Mediator
Priorität: 8/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Mediator wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Mediator - macht fachliche Entscheidungen austauschbar und testbar.
public final class MediatorOrderPolicy {
    private final java.util.List<OrderRule> rules;
    public MediatorOrderPolicy(java.util.List<OrderRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(OrderRequest request) {
        for (OrderRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface OrderRule { void validate(OrderRequest request); }
final class PositiveAmountRule implements OrderRule {
    public void validate(OrderRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp031: State im Enterprise-Kontext sauber einsetzen

Englischer Begriff: State
Priorität: 8/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: State wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: State - macht fachliche Entscheidungen austauschbar und testbar.
public final class StateCustomerPolicy {
    private final java.util.List<CustomerRule> rules;
    public StateCustomerPolicy(java.util.List<CustomerRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(CustomerRequest request) {
        for (CustomerRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface CustomerRule { void validate(CustomerRequest request); }
final class PositiveAmountRule implements CustomerRule {
    public void validate(CustomerRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp032: Specification im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Specification
Priorität: 8/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Specification wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Specification - macht fachliche Entscheidungen austauschbar und testbar.
public final class SpecificationPaymentPolicy {
    private final java.util.List<PaymentRule> rules;
    public SpecificationPaymentPolicy(java.util.List<PaymentRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(PaymentRequest request) {
        for (PaymentRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface PaymentRule { void validate(PaymentRequest request); }
final class PositiveAmountRule implements PaymentRule {
    public void validate(PaymentRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp033: Iterator im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Iterator
Priorität: 8/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Iterator wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Iterator - macht fachliche Entscheidungen austauschbar und testbar.
public final class IteratorPartnerPolicy {
    private final java.util.List<PartnerRule> rules;
    public IteratorPartnerPolicy(java.util.List<PartnerRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(PartnerRequest request) {
        for (PartnerRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface PartnerRule { void validate(PartnerRequest request); }
final class PositiveAmountRule implements PartnerRule {
    public void validate(PartnerRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp034: Visitor im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Visitor
Priorität: 7/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Visitor wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Visitor - macht fachliche Entscheidungen austauschbar und testbar.
public final class VisitorAccountPolicy {
    private final java.util.List<AccountRule> rules;
    public VisitorAccountPolicy(java.util.List<AccountRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(AccountRequest request) {
        for (AccountRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface AccountRule { void validate(AccountRequest request); }
final class PositiveAmountRule implements AccountRule {
    public void validate(AccountRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp035: Policy im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Policy
Priorität: 7/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Policy wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Policy - macht fachliche Entscheidungen austauschbar und testbar.
public final class PolicyProductPolicy {
    private final java.util.List<ProductRule> rules;
    public PolicyProductPolicy(java.util.List<ProductRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(ProductRequest request) {
        for (ProductRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface ProductRule { void validate(ProductRequest request); }
final class PositiveAmountRule implements ProductRule {
    public void validate(ProductRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp036: Null Object im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Null Object
Priorität: 7/10
Kategorie: Verhaltensmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Null Object wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Null Object - macht fachliche Entscheidungen austauschbar und testbar.
public final class NullObjectOrderPolicy {
    private final java.util.List<OrderRule> rules;
    public NullObjectOrderPolicy(java.util.List<OrderRule> rules) { this.rules = java.util.List.copyOf(rules); }

    public void check(OrderRequest request) {
        for (OrderRule rule : rules) {
            rule.validate(request);
        }
    }
}

interface OrderRule { void validate(OrderRequest request); }
final class PositiveAmountRule implements OrderRule {
    public void validate(OrderRequest r) { if (r.amount().signum() <= 0) throw new IllegalArgumentException("amount must be positive"); }
}
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Enterprise-Architekturmuster (Enterprise Architecture Patterns)

Transaktionen, Integration, Schichten, Ports, Adapter und fachliche Systemgrenzen.

Enterprise-Architekturmuster

dp037: Layered Architecture im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Layered Architecture
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Layered Architecture wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Layered Architecture - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp038: Hexagonal Architecture im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Hexagonal Architecture
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Hexagonal Architecture wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Hexagonal Architecture - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp039: Clean Architecture im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Clean Architecture
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Clean Architecture wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Clean Architecture - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp040: Ports and Adapters im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Ports and Adapters
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Ports and Adapters wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Ports and Adapters - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp041: Service Layer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Service Layer
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Service Layer wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Service Layer - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp042: Application Service im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Application Service
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Application Service wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Application Service - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }

dp043: Transaction Script im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Transaction Script
Priorität: 10/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Transaction Script wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Transaction Script - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp044: Domain Model im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Domain Model
Priorität: 8/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Domain Model wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Domain Model - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp045: Unit of Work im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Unit of Work
Priorität: 8/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Unit of Work wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Unit of Work - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp046: Repository im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Repository
Priorität: 7/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Repository wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Repository - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp047: DTO im Enterprise-Kontext sauber einsetzen

Englischer Begriff: DTO
Priorität: 7/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: DTO wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: DTO - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp048: CQRS im Enterprise-Kontext sauber einsetzen

Englischer Begriff: CQRS
Priorität: 7/10
Kategorie: Enterprise-Architekturmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: CQRS wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: CQRS - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }
Integrationsmuster (Integration Patterns)

Nachrichten, Schnittstellen, Transformation, Routing, Entkopplung und Partnerkommunikation.

Integrationsmuster

dp049: Message Channel im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Message Channel
Priorität: 9/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Message Channel wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Message Channel - trennt interne Domain von externer Schnittstelle.
public final class MessageChannelCustomerAdapter {
    private final ExternalCustomerClient client;
    public MessageChannelCustomerAdapter(ExternalCustomerClient client) { this.client = client; }

    public CustomerResult submit(CustomerRequest request) {
        ExternalCustomerPayload payload = new ExternalCustomerPayload(request.id(), request.amount().toPlainString());
        ExternalCustomerResponse response = client.send(payload);
        return new CustomerResult(response.reference(), response.accepted());
    }
}

interface ExternalCustomerClient { ExternalCustomerResponse send(ExternalCustomerPayload payload); }
record ExternalCustomerPayload(String id, String amount) { }
record ExternalCustomerResponse(String reference, boolean accepted) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp050: Message Router im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Message Router
Priorität: 9/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Message Router wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Message Router - trennt interne Domain von externer Schnittstelle.
public final class MessageRouterPaymentAdapter {
    private final ExternalPaymentClient client;
    public MessageRouterPaymentAdapter(ExternalPaymentClient client) { this.client = client; }

    public PaymentResult submit(PaymentRequest request) {
        ExternalPaymentPayload payload = new ExternalPaymentPayload(request.id(), request.amount().toPlainString());
        ExternalPaymentResponse response = client.send(payload);
        return new PaymentResult(response.reference(), response.accepted());
    }
}

interface ExternalPaymentClient { ExternalPaymentResponse send(ExternalPaymentPayload payload); }
record ExternalPaymentPayload(String id, String amount) { }
record ExternalPaymentResponse(String reference, boolean accepted) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp051: Content-Based Router im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Content-Based Router
Priorität: 9/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Content-Based Router wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Content-Based Router - trennt interne Domain von externer Schnittstelle.
public final class ContentBasedRouterPartnerAdapter {
    private final ExternalPartnerClient client;
    public ContentBasedRouterPartnerAdapter(ExternalPartnerClient client) { this.client = client; }

    public PartnerResult submit(PartnerRequest request) {
        ExternalPartnerPayload payload = new ExternalPartnerPayload(request.id(), request.amount().toPlainString());
        ExternalPartnerResponse response = client.send(payload);
        return new PartnerResult(response.reference(), response.accepted());
    }
}

interface ExternalPartnerClient { ExternalPartnerResponse send(ExternalPartnerPayload payload); }
record ExternalPartnerPayload(String id, String amount) { }
record ExternalPartnerResponse(String reference, boolean accepted) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp052: Message Translator im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Message Translator
Priorität: 9/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Message Translator wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Message Translator - trennt interne Domain von externer Schnittstelle.
public final class MessageTranslatorAccountAdapter {
    private final ExternalAccountClient client;
    public MessageTranslatorAccountAdapter(ExternalAccountClient client) { this.client = client; }

    public AccountResult submit(AccountRequest request) {
        ExternalAccountPayload payload = new ExternalAccountPayload(request.id(), request.amount().toPlainString());
        ExternalAccountResponse response = client.send(payload);
        return new AccountResult(response.reference(), response.accepted());
    }
}

interface ExternalAccountClient { ExternalAccountResponse send(ExternalAccountPayload payload); }
record ExternalAccountPayload(String id, String amount) { }
record ExternalAccountResponse(String reference, boolean accepted) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp053: Envelope Wrapper im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Envelope Wrapper
Priorität: 9/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Envelope Wrapper wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Envelope Wrapper - trennt interne Domain von externer Schnittstelle.
public final class EnvelopeWrapperProductAdapter {
    private final ExternalProductClient client;
    public EnvelopeWrapperProductAdapter(ExternalProductClient client) { this.client = client; }

    public ProductResult submit(ProductRequest request) {
        ExternalProductPayload payload = new ExternalProductPayload(request.id(), request.amount().toPlainString());
        ExternalProductResponse response = client.send(payload);
        return new ProductResult(response.reference(), response.accepted());
    }
}

interface ExternalProductClient { ExternalProductResponse send(ExternalProductPayload payload); }
record ExternalProductPayload(String id, String amount) { }
record ExternalProductResponse(String reference, boolean accepted) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp054: Claim Check im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Claim Check
Priorität: 8/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Claim Check wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Claim Check - trennt interne Domain von externer Schnittstelle.
public final class ClaimCheckOrderAdapter {
    private final ExternalOrderClient client;
    public ClaimCheckOrderAdapter(ExternalOrderClient client) { this.client = client; }

    public OrderResult submit(OrderRequest request) {
        ExternalOrderPayload payload = new ExternalOrderPayload(request.id(), request.amount().toPlainString());
        ExternalOrderResponse response = client.send(payload);
        return new OrderResult(response.reference(), response.accepted());
    }
}

interface ExternalOrderClient { ExternalOrderResponse send(ExternalOrderPayload payload); }
record ExternalOrderPayload(String id, String amount) { }
record ExternalOrderResponse(String reference, boolean accepted) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp055: Idempotent Receiver im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Idempotent Receiver
Priorität: 8/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Idempotent Receiver wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Idempotent Receiver - trennt interne Domain von externer Schnittstelle.
public final class IdempotentReceiverCustomerAdapter {
    private final ExternalCustomerClient client;
    public IdempotentReceiverCustomerAdapter(ExternalCustomerClient client) { this.client = client; }

    public CustomerResult submit(CustomerRequest request) {
        ExternalCustomerPayload payload = new ExternalCustomerPayload(request.id(), request.amount().toPlainString());
        ExternalCustomerResponse response = client.send(payload);
        return new CustomerResult(response.reference(), response.accepted());
    }
}

interface ExternalCustomerClient { ExternalCustomerResponse send(ExternalCustomerPayload payload); }
record ExternalCustomerPayload(String id, String amount) { }
record ExternalCustomerResponse(String reference, boolean accepted) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp056: Polling Consumer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Polling Consumer
Priorität: 8/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Polling Consumer wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Polling Consumer - trennt interne Domain von externer Schnittstelle.
public final class PollingConsumerPaymentAdapter {
    private final ExternalPaymentClient client;
    public PollingConsumerPaymentAdapter(ExternalPaymentClient client) { this.client = client; }

    public PaymentResult submit(PaymentRequest request) {
        ExternalPaymentPayload payload = new ExternalPaymentPayload(request.id(), request.amount().toPlainString());
        ExternalPaymentResponse response = client.send(payload);
        return new PaymentResult(response.reference(), response.accepted());
    }
}

interface ExternalPaymentClient { ExternalPaymentResponse send(ExternalPaymentPayload payload); }
record ExternalPaymentPayload(String id, String amount) { }
record ExternalPaymentResponse(String reference, boolean accepted) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp057: Event-Driven Consumer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Event-Driven Consumer
Priorität: 8/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Event-Driven Consumer wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Event-Driven Consumer - trennt interne Domain von externer Schnittstelle.
public final class EventDrivenConsumerPartnerAdapter {
    private final ExternalPartnerClient client;
    public EventDrivenConsumerPartnerAdapter(ExternalPartnerClient client) { this.client = client; }

    public PartnerResult submit(PartnerRequest request) {
        ExternalPartnerPayload payload = new ExternalPartnerPayload(request.id(), request.amount().toPlainString());
        ExternalPartnerResponse response = client.send(payload);
        return new PartnerResult(response.reference(), response.accepted());
    }
}

interface ExternalPartnerClient { ExternalPartnerResponse send(ExternalPartnerPayload payload); }
record ExternalPartnerPayload(String id, String amount) { }
record ExternalPartnerResponse(String reference, boolean accepted) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp058: Dead Letter Channel im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Dead Letter Channel
Priorität: 7/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Dead Letter Channel wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Dead Letter Channel - trennt interne Domain von externer Schnittstelle.
public final class DeadLetterChannelAccountAdapter {
    private final ExternalAccountClient client;
    public DeadLetterChannelAccountAdapter(ExternalAccountClient client) { this.client = client; }

    public AccountResult submit(AccountRequest request) {
        ExternalAccountPayload payload = new ExternalAccountPayload(request.id(), request.amount().toPlainString());
        ExternalAccountResponse response = client.send(payload);
        return new AccountResult(response.reference(), response.accepted());
    }
}

interface ExternalAccountClient { ExternalAccountResponse send(ExternalAccountPayload payload); }
record ExternalAccountPayload(String id, String amount) { }
record ExternalAccountResponse(String reference, boolean accepted) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp059: Outbox im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Outbox
Priorität: 7/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Outbox wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Outbox - trennt interne Domain von externer Schnittstelle.
public final class OutboxProductAdapter {
    private final ExternalProductClient client;
    public OutboxProductAdapter(ExternalProductClient client) { this.client = client; }

    public ProductResult submit(ProductRequest request) {
        ExternalProductPayload payload = new ExternalProductPayload(request.id(), request.amount().toPlainString());
        ExternalProductResponse response = client.send(payload);
        return new ProductResult(response.reference(), response.accepted());
    }
}

interface ExternalProductClient { ExternalProductResponse send(ExternalProductPayload payload); }
record ExternalProductPayload(String id, String amount) { }
record ExternalProductResponse(String reference, boolean accepted) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp060: Saga im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Saga
Priorität: 7/10
Kategorie: Integrationsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Saga wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Saga - trennt interne Domain von externer Schnittstelle.
public final class SagaOrderAdapter {
    private final ExternalOrderClient client;
    public SagaOrderAdapter(ExternalOrderClient client) { this.client = client; }

    public OrderResult submit(OrderRequest request) {
        ExternalOrderPayload payload = new ExternalOrderPayload(request.id(), request.amount().toPlainString());
        ExternalOrderResponse response = client.send(payload);
        return new OrderResult(response.reference(), response.accepted());
    }
}

interface ExternalOrderClient { ExternalOrderResponse send(ExternalOrderPayload payload); }
record ExternalOrderPayload(String id, String amount) { }
record ExternalOrderResponse(String reference, boolean accepted) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Domain-Driven-Design-Muster (DDD Patterns)

Fachliche Modelle, Aggregate, Value Objects, Services, Repositories und Bounded Contexts.

Domain-Driven-Design-Muster

dp061: Entity im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Entity
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Entity wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Entity - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp062: Value Object im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Value Object
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Value Object wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Value Object - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp063: Aggregate Root im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Aggregate Root
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Aggregate Root wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Aggregate Root - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp064: Domain Service im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Domain Service
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Domain Service wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Domain Service - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp065: Domain Event im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Domain Event
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Domain Event wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Domain Event - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp066: Repository im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Repository
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Repository wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Repository - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }

dp067: Factory im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Factory
Priorität: 10/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Factory wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Factory - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp068: Bounded Context im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Bounded Context
Priorität: 8/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Bounded Context wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Bounded Context - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp069: Context Map im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Context Map
Priorität: 8/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Context Map wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Context Map - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp070: Specification im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Specification
Priorität: 7/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Specification wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Specification - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp071: Anti-Corruption Layer im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Anti-Corruption Layer
Priorität: 7/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Anti-Corruption Layer wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Anti-Corruption Layer - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp072: Ubiquitous Language im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Ubiquitous Language
Priorität: 7/10
Kategorie: Domain-Driven-Design-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Ubiquitous Language wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Ubiquitous Language - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }
Cloud- und Resilience-Muster (Cloud / Resilience Patterns)

Fehlertoleranz, Lastbegrenzung, Skalierung, Wiederholung und Stabilität im Betrieb.

Cloud- und Resilience-Muster

dp073: Circuit Breaker im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Circuit Breaker
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Circuit Breaker wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Circuit Breaker - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class CircuitBreakerCustomerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureCustomerClient client;
    public CircuitBreakerCustomerGuard(SecureCustomerClient client) { this.client = client; }

    public CustomerResult call(CustomerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("CUSTOMER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent customer calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureCustomerClient { CustomerResult submit(CustomerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp074: Retry im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Retry
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Retry wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Retry - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class RetryPaymentGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePaymentClient client;
    public RetryPaymentGuard(SecurePaymentClient client) { this.client = client; }

    public PaymentResult call(PaymentRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PAYMENT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent payment calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePaymentClient { PaymentResult submit(PaymentRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp075: Timeout im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Timeout
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Timeout wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Timeout - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class TimeoutPartnerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePartnerClient client;
    public TimeoutPartnerGuard(SecurePartnerClient client) { this.client = client; }

    public PartnerResult call(PartnerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PARTNER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent partner calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePartnerClient { PartnerResult submit(PartnerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp076: Bulkhead im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Bulkhead
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Bulkhead wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Bulkhead - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class BulkheadAccountGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureAccountClient client;
    public BulkheadAccountGuard(SecureAccountClient client) { this.client = client; }

    public AccountResult call(AccountRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ACCOUNT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent account calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureAccountClient { AccountResult submit(AccountRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp077: Rate Limiter im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Rate Limiter
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Rate Limiter wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Rate Limiter - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class RateLimiterProductGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureProductClient client;
    public RateLimiterProductGuard(SecureProductClient client) { this.client = client; }

    public ProductResult call(ProductRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PRODUCT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent product calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureProductClient { ProductResult submit(ProductRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp078: Backpressure im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Backpressure
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Backpressure wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Backpressure - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class BackpressureOrderGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureOrderClient client;
    public BackpressureOrderGuard(SecureOrderClient client) { this.client = client; }

    public OrderResult call(OrderRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ORDER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent order calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureOrderClient { OrderResult submit(OrderRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp079: Fallback im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Fallback
Priorität: 10/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Fallback wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Fallback - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class FallbackCustomerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureCustomerClient client;
    public FallbackCustomerGuard(SecureCustomerClient client) { this.client = client; }

    public CustomerResult call(CustomerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("CUSTOMER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent customer calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureCustomerClient { CustomerResult submit(CustomerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp080: Health Check im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Health Check
Priorität: 8/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Health Check wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Health Check - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class HealthCheckPaymentGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePaymentClient client;
    public HealthCheckPaymentGuard(SecurePaymentClient client) { this.client = client; }

    public PaymentResult call(PaymentRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PAYMENT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent payment calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePaymentClient { PaymentResult submit(PaymentRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp081: Graceful Degradation im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Graceful Degradation
Priorität: 8/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Graceful Degradation wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Graceful Degradation - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class GracefulDegradationPartnerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePartnerClient client;
    public GracefulDegradationPartnerGuard(SecurePartnerClient client) { this.client = client; }

    public PartnerResult call(PartnerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PARTNER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent partner calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePartnerClient { PartnerResult submit(PartnerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp082: Load Shedding im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Load Shedding
Priorität: 7/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Load Shedding wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Load Shedding - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class LoadSheddingAccountGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureAccountClient client;
    public LoadSheddingAccountGuard(SecureAccountClient client) { this.client = client; }

    public AccountResult call(AccountRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ACCOUNT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent account calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureAccountClient { AccountResult submit(AccountRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp083: Leader Election im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Leader Election
Priorität: 7/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Leader Election wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Leader Election - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class LeaderElectionProductGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureProductClient client;
    public LeaderElectionProductGuard(SecureProductClient client) { this.client = client; }

    public ProductResult call(ProductRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PRODUCT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent product calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureProductClient { ProductResult submit(ProductRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp084: Sidecar im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Sidecar
Priorität: 7/10
Kategorie: Cloud- und Resilience-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Sidecar wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Sidecar - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class SidecarOrderGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureOrderClient client;
    public SidecarOrderGuard(SecureOrderClient client) { this.client = client; }

    public OrderResult call(OrderRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ORDER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent order calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureOrderClient { OrderResult submit(OrderRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Security- und Governance-Muster (Security / Governance Patterns)

Autorisierung, Audit, Datenschutz, Richtlinien und sichere Verarbeitung.

Security- und Governance-Muster

dp085: Policy Enforcement Point im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Policy Enforcement Point
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Policy Enforcement Point wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Policy Enforcement Point - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class PolicyEnforcementPointCustomerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureCustomerClient client;
    public PolicyEnforcementPointCustomerGuard(SecureCustomerClient client) { this.client = client; }

    public CustomerResult call(CustomerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("CUSTOMER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent customer calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureCustomerClient { CustomerResult submit(CustomerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp086: Policy Decision Point im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Policy Decision Point
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Policy Decision Point wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Policy Decision Point - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class PolicyDecisionPointPaymentGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePaymentClient client;
    public PolicyDecisionPointPaymentGuard(SecurePaymentClient client) { this.client = client; }

    public PaymentResult call(PaymentRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PAYMENT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent payment calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePaymentClient { PaymentResult submit(PaymentRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp087: Audit Trail im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Audit Trail
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Audit Trail wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Audit Trail - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class AuditTrailPartnerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePartnerClient client;
    public AuditTrailPartnerGuard(SecurePartnerClient client) { this.client = client; }

    public PartnerResult call(PartnerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PARTNER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent partner calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePartnerClient { PartnerResult submit(PartnerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp088: Token Relay im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Token Relay
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Token Relay wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Token Relay - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class TokenRelayAccountGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureAccountClient client;
    public TokenRelayAccountGuard(SecureAccountClient client) { this.client = client; }

    public AccountResult call(AccountRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ACCOUNT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent account calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureAccountClient { AccountResult submit(AccountRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp089: Input Validation im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Input Validation
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Input Validation wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Input Validation - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class InputValidationProductGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureProductClient client;
    public InputValidationProductGuard(SecureProductClient client) { this.client = client; }

    public ProductResult call(ProductRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PRODUCT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent product calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureProductClient { ProductResult submit(ProductRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp090: Output Encoding im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Output Encoding
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Output Encoding wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Output Encoding - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class OutputEncodingOrderGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureOrderClient client;
    public OutputEncodingOrderGuard(SecureOrderClient client) { this.client = client; }

    public OrderResult call(OrderRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ORDER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent order calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureOrderClient { OrderResult submit(OrderRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp091: Secure Logger im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Secure Logger
Priorität: 10/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Secure Logger wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Secure Logger - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class SecureLoggerCustomerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureCustomerClient client;
    public SecureLoggerCustomerGuard(SecureCustomerClient client) { this.client = client; }

    public CustomerResult call(CustomerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("CUSTOMER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent customer calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureCustomerClient { CustomerResult submit(CustomerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record CustomerResult(String reference, boolean accepted) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp092: Secrets Provider im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Secrets Provider
Priorität: 8/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Secrets Provider wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Secrets Provider - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class SecretsProviderPaymentGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePaymentClient client;
    public SecretsProviderPaymentGuard(SecurePaymentClient client) { this.client = client; }

    public PaymentResult call(PaymentRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PAYMENT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent payment calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePaymentClient { PaymentResult submit(PaymentRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PaymentResult(String reference, boolean accepted) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp093: Access Control List im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Access Control List
Priorität: 8/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Access Control List wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Access Control List - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class AccessControlListPartnerGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecurePartnerClient client;
    public AccessControlListPartnerGuard(SecurePartnerClient client) { this.client = client; }

    public PartnerResult call(PartnerRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PARTNER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent partner calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecurePartnerClient { PartnerResult submit(PartnerRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record PartnerResult(String reference, boolean accepted) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp094: Permission Matrix im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Permission Matrix
Priorität: 7/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Permission Matrix wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Permission Matrix - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class PermissionMatrixAccountGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureAccountClient client;
    public PermissionMatrixAccountGuard(SecureAccountClient client) { this.client = client; }

    public AccountResult call(AccountRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ACCOUNT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent account calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureAccountClient { AccountResult submit(AccountRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record AccountResult(String reference, boolean accepted) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp095: Data Masking im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Data Masking
Priorität: 7/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Data Masking wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Data Masking - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class DataMaskingProductGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureProductClient client;
    public DataMaskingProductGuard(SecureProductClient client) { this.client = client; }

    public ProductResult call(ProductRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("PRODUCT_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent product calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureProductClient { ProductResult submit(ProductRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record ProductResult(String reference, boolean accepted) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp096: Least Privilege im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Least Privilege
Priorität: 7/10
Kategorie: Security- und Governance-Muster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Least Privilege wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Least Privilege - schuetzt Systemgrenzen vor Last, Fehlern oder Missbrauch.
public final class LeastPrivilegeOrderGuard {
    private final java.util.concurrent.Semaphore permits = new java.util.concurrent.Semaphore(20);
    private final SecureOrderClient client;
    public LeastPrivilegeOrderGuard(SecureOrderClient client) { this.client = client; }

    public OrderResult call(OrderRequest request, UserContext user) throws InterruptedException {
        if (!user.permissions().contains("ORDER_WRITE")) throw new SecurityException("missing permission");
        if (!permits.tryAcquire()) throw new IllegalStateException("too many concurrent order calls");
        try { return client.submit(request); }
        finally { permits.release(); }
    }
}

interface SecureOrderClient { OrderResult submit(OrderRequest request); }
record UserContext(String name, java.util.Set<String> permissions) { }
record OrderResult(String reference, boolean accepted) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
Persistenz- und Datenmuster (Persistence / Data Patterns)

Transaktionsgrenzen, Abfragen, Optimistic Locking, Caching und Datenkonsistenz.

Persistenz- und Datenmuster

dp097: Data Mapper im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Data Mapper
Priorität: 9/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Data Mapper wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Data Mapper - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp098: Active Record im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Active Record
Priorität: 9/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Active Record wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Active Record - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp099: Lazy Loading im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Lazy Loading
Priorität: 9/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Lazy Loading wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Lazy Loading - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp100: Eager Loading im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Eager Loading
Priorität: 9/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Eager Loading wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Eager Loading - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp101: Optimistic Locking im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Optimistic Locking
Priorität: 9/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Optimistic Locking wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Optimistic Locking - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp102: Pessimistic Locking im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Pessimistic Locking
Priorität: 8/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Pessimistic Locking wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Pessimistic Locking - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }

dp103: Identity Map im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Identity Map
Priorität: 8/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Identity Map wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Identity Map - haelt Fachlogik an einer klaren Modellgrenze.
public final class CustomerApplicationService {
    private final CustomerRepository repository;
    public CustomerApplicationService(CustomerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Customer aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Customer {
    private final String id;
    private boolean approved;
    Customer(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface CustomerRepository { Customer get(String id); void save(Customer aggregate); }

dp104: Query Object im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Query Object
Priorität: 8/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Query Object wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Query Object - haelt Fachlogik an einer klaren Modellgrenze.
public final class PaymentApplicationService {
    private final PaymentRepository repository;
    public PaymentApplicationService(PaymentRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Payment aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Payment {
    private final String id;
    private boolean approved;
    Payment(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PaymentRepository { Payment get(String id); void save(Payment aggregate); }

dp105: Cache Aside im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Cache Aside
Priorität: 8/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Cache Aside wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Cache Aside - haelt Fachlogik an einer klaren Modellgrenze.
public final class PartnerApplicationService {
    private final PartnerRepository repository;
    public PartnerApplicationService(PartnerRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Partner aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Partner {
    private final String id;
    private boolean approved;
    Partner(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface PartnerRepository { Partner get(String id); void save(Partner aggregate); }

dp106: Read Model im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Read Model
Priorität: 7/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Read Model wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Read Model - haelt Fachlogik an einer klaren Modellgrenze.
public final class AccountApplicationService {
    private final AccountRepository repository;
    public AccountApplicationService(AccountRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Account aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Account {
    private final String id;
    private boolean approved;
    Account(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface AccountRepository { Account get(String id); void save(Account aggregate); }

dp107: Database per Service im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Database per Service
Priorität: 7/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Database per Service wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Database per Service - haelt Fachlogik an einer klaren Modellgrenze.
public final class ProductApplicationService {
    private final ProductRepository repository;
    public ProductApplicationService(ProductRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Product aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Product {
    private final String id;
    private boolean approved;
    Product(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface ProductRepository { Product get(String id); void save(Product aggregate); }

dp108: Migration Script im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Migration Script
Priorität: 7/10
Kategorie: Persistenz- und Datenmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Migration Script wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Migration Script - haelt Fachlogik an einer klaren Modellgrenze.
public final class OrderApplicationService {
    private final OrderRepository repository;
    public OrderApplicationService(OrderRepository repository) { this.repository = repository; }

    public void approve(String id) {
        Order aggregate = repository.get(id);
        aggregate.approve();
        repository.save(aggregate);
    }
}

final class Order {
    private final String id;
    private boolean approved;
    Order(String id) { this.id = id; }
    void approve() { if (approved) throw new IllegalStateException("already approved"); approved = true; }
}
interface OrderRepository { Order get(String id); void save(Order aggregate); }
Testbarkeits- und Qualitätsmuster (Testing / Quality Patterns)

Testbarkeit, Simulation, Vertragsprüfung, Fixtures und Architekturregeln.

Testbarkeits- und Qualitätsmuster

dp109: Test Double im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Test Double
Priorität: 9/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Test Double wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Test Double - macht Verhalten isoliert pruefbar.
public final class TestDoubleCustomerTestFixture {
    public static CustomerRequest validPartnerRequest() {
        return new CustomerRequest("customer-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryCustomerRepository repositoryWith(Customer aggregate) {
        InMemoryCustomerRepository repo = new InMemoryCustomerRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryCustomerRepository {
    private final java.util.Map<String,Customer> store = new java.util.HashMap<>();
    void save(Customer aggregate) { store.put(aggregate.id(), aggregate); }
}
record Customer(String id) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp110: Mock im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Mock
Priorität: 9/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Mock wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Mock - macht Verhalten isoliert pruefbar.
public final class MockPaymentTestFixture {
    public static PaymentRequest validPartnerRequest() {
        return new PaymentRequest("payment-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryPaymentRepository repositoryWith(Payment aggregate) {
        InMemoryPaymentRepository repo = new InMemoryPaymentRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryPaymentRepository {
    private final java.util.Map<String,Payment> store = new java.util.HashMap<>();
    void save(Payment aggregate) { store.put(aggregate.id(), aggregate); }
}
record Payment(String id) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp111: Stub im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Stub
Priorität: 9/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Stub wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Stub - macht Verhalten isoliert pruefbar.
public final class StubPartnerTestFixture {
    public static PartnerRequest validPartnerRequest() {
        return new PartnerRequest("partner-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryPartnerRepository repositoryWith(Partner aggregate) {
        InMemoryPartnerRepository repo = new InMemoryPartnerRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryPartnerRepository {
    private final java.util.Map<String,Partner> store = new java.util.HashMap<>();
    void save(Partner aggregate) { store.put(aggregate.id(), aggregate); }
}
record Partner(String id) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp112: Fake im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Fake
Priorität: 9/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Fake wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Fake - macht Verhalten isoliert pruefbar.
public final class FakeAccountTestFixture {
    public static AccountRequest validPartnerRequest() {
        return new AccountRequest("account-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryAccountRepository repositoryWith(Account aggregate) {
        InMemoryAccountRepository repo = new InMemoryAccountRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryAccountRepository {
    private final java.util.Map<String,Account> store = new java.util.HashMap<>();
    void save(Account aggregate) { store.put(aggregate.id(), aggregate); }
}
record Account(String id) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp113: Contract Test im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Contract Test
Priorität: 9/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Contract Test wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Contract Test - macht Verhalten isoliert pruefbar.
public final class ContractTestProductTestFixture {
    public static ProductRequest validPartnerRequest() {
        return new ProductRequest("product-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryProductRepository repositoryWith(Product aggregate) {
        InMemoryProductRepository repo = new InMemoryProductRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryProductRepository {
    private final java.util.Map<String,Product> store = new java.util.HashMap<>();
    void save(Product aggregate) { store.put(aggregate.id(), aggregate); }
}
record Product(String id) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp114: Golden Master im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Golden Master
Priorität: 8/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Golden Master wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Golden Master - macht Verhalten isoliert pruefbar.
public final class GoldenMasterOrderTestFixture {
    public static OrderRequest validPartnerRequest() {
        return new OrderRequest("order-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryOrderRepository repositoryWith(Order aggregate) {
        InMemoryOrderRepository repo = new InMemoryOrderRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryOrderRepository {
    private final java.util.Map<String,Order> store = new java.util.HashMap<>();
    void save(Order aggregate) { store.put(aggregate.id(), aggregate); }
}
record Order(String id) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

dp115: Characterization Test im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Characterization Test
Priorität: 8/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Customer-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Customer-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Characterization Test wird als Selbstzweck eingebaut, waehrend die eigentliche Customer-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class CustomerProcessor {
    public void process(CustomerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown customer type: " + request.type());
        }
    }

    private void validateStandard(CustomerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(CustomerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(CustomerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(CustomerRequest request) { /* JMS/REST an Partner */ }
}

record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Characterization Test - macht Verhalten isoliert pruefbar.
public final class CharacterizationTestCustomerTestFixture {
    public static CustomerRequest validPartnerRequest() {
        return new CustomerRequest("customer-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryCustomerRepository repositoryWith(Customer aggregate) {
        InMemoryCustomerRepository repo = new InMemoryCustomerRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryCustomerRepository {
    private final java.util.Map<String,Customer> store = new java.util.HashMap<>();
    void save(Customer aggregate) { store.put(aggregate.id(), aggregate); }
}
record Customer(String id) { }
record CustomerRequest(String id, String type, java.math.BigDecimal amount) { }

dp116: Approval Test im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Approval Test
Priorität: 8/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Payment-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Payment-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Approval Test wird als Selbstzweck eingebaut, waehrend die eigentliche Payment-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PaymentProcessor {
    public void process(PaymentRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown payment type: " + request.type());
        }
    }

    private void validateStandard(PaymentRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PaymentRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PaymentRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PaymentRequest request) { /* JMS/REST an Partner */ }
}

record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Approval Test - macht Verhalten isoliert pruefbar.
public final class ApprovalTestPaymentTestFixture {
    public static PaymentRequest validPartnerRequest() {
        return new PaymentRequest("payment-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryPaymentRepository repositoryWith(Payment aggregate) {
        InMemoryPaymentRepository repo = new InMemoryPaymentRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryPaymentRepository {
    private final java.util.Map<String,Payment> store = new java.util.HashMap<>();
    void save(Payment aggregate) { store.put(aggregate.id(), aggregate); }
}
record Payment(String id) { }
record PaymentRequest(String id, String type, java.math.BigDecimal amount) { }

dp117: Fixture Object im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Fixture Object
Priorität: 8/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Partner-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Partner-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Fixture Object wird als Selbstzweck eingebaut, waehrend die eigentliche Partner-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class PartnerProcessor {
    public void process(PartnerRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown partner type: " + request.type());
        }
    }

    private void validateStandard(PartnerRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(PartnerRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(PartnerRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(PartnerRequest request) { /* JMS/REST an Partner */ }
}

record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Fixture Object - macht Verhalten isoliert pruefbar.
public final class FixtureObjectPartnerTestFixture {
    public static PartnerRequest validPartnerRequest() {
        return new PartnerRequest("partner-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryPartnerRepository repositoryWith(Partner aggregate) {
        InMemoryPartnerRepository repo = new InMemoryPartnerRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryPartnerRepository {
    private final java.util.Map<String,Partner> store = new java.util.HashMap<>();
    void save(Partner aggregate) { store.put(aggregate.id(), aggregate); }
}
record Partner(String id) { }
record PartnerRequest(String id, String type, java.math.BigDecimal amount) { }

dp118: Architecture Test im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Architecture Test
Priorität: 7/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Account-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Account-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Architecture Test wird als Selbstzweck eingebaut, waehrend die eigentliche Account-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class AccountProcessor {
    public void process(AccountRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown account type: " + request.type());
        }
    }

    private void validateStandard(AccountRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(AccountRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(AccountRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(AccountRequest request) { /* JMS/REST an Partner */ }
}

record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Architecture Test - macht Verhalten isoliert pruefbar.
public final class ArchitectureTestAccountTestFixture {
    public static AccountRequest validPartnerRequest() {
        return new AccountRequest("account-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryAccountRepository repositoryWith(Account aggregate) {
        InMemoryAccountRepository repo = new InMemoryAccountRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryAccountRepository {
    private final java.util.Map<String,Account> store = new java.util.HashMap<>();
    void save(Account aggregate) { store.put(aggregate.id(), aggregate); }
}
record Account(String id) { }
record AccountRequest(String id, String type, java.math.BigDecimal amount) { }

dp119: Mutation Testing im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Mutation Testing
Priorität: 7/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Product-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Product-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Mutation Testing wird als Selbstzweck eingebaut, waehrend die eigentliche Product-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class ProductProcessor {
    public void process(ProductRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown product type: " + request.type());
        }
    }

    private void validateStandard(ProductRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(ProductRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(ProductRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(ProductRequest request) { /* JMS/REST an Partner */ }
}

record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Mutation Testing - macht Verhalten isoliert pruefbar.
public final class MutationTestingProductTestFixture {
    public static ProductRequest validPartnerRequest() {
        return new ProductRequest("product-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryProductRepository repositoryWith(Product aggregate) {
        InMemoryProductRepository repo = new InMemoryProductRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryProductRepository {
    private final java.util.Map<String,Product> store = new java.util.HashMap<>();
    void save(Product aggregate) { store.put(aggregate.id(), aggregate); }
}
record Product(String id) { }
record ProductRequest(String id, String type, java.math.BigDecimal amount) { }

dp120: Property-Based Test im Enterprise-Kontext sauber einsetzen

Englischer Begriff: Property-Based Test
Priorität: 7/10
Kategorie: Testbarkeits- und Qualitätsmuster

Warum wichtig: Das Muster hilft, fachliche Order-Logik von technischer Kopplung zu trennen und Aenderungen kontrolliert einzubauen.

Wann einsetzen: Einsetzen, wenn Order-Varianten, Integrationsgrenzen oder wiederkehrende Entscheidungen nicht mehr sicher durch einfache Methoden ausdrueckbar sind.

Typischer Fehler: Property-Based Test wird als Selbstzweck eingebaut, waehrend die eigentliche Order-Regel weiterhin in Controllern, Jobs oder Clients verstreut bleibt.

Enterprise-Einordnung: Relevant fuer Legacy-Modernisierung, modulare Maven-Projekte, Spring/Jakarta Services, OpenShift-Betrieb und testbare Fachgrenzen.

Ausgangspunkt-Code

public class OrderProcessor {
    public void process(OrderRequest request) {
        if (request.type().equals("STANDARD")) {
            validateStandard(request);
            sendToCoreSystem(request);
        } else if (request.type().equals("PARTNER")) {
            validatePartner(request);
            sendToPartnerGateway(request);
        } else {
            throw new IllegalArgumentException("Unknown order type: " + request.type());
        }
    }

    private void validateStandard(OrderRequest request) { /* konkrete Pflichtfeldpruefung */ }
    private void validatePartner(OrderRequest request) { /* konkrete Partner-Regel */ }
    private void sendToCoreSystem(OrderRequest request) { /* REST-Aufruf an Core */ }
    private void sendToPartnerGateway(OrderRequest request) { /* JMS/REST an Partner */ }
}

record OrderRequest(String id, String type, java.math.BigDecimal amount) { }

Ziel-Code

// Pattern: Property-Based Test - macht Verhalten isoliert pruefbar.
public final class PropertyBasedTestOrderTestFixture {
    public static OrderRequest validPartnerRequest() {
        return new OrderRequest("order-4711", "PARTNER", new java.math.BigDecimal("42.50"));
    }

    public static InMemoryOrderRepository repositoryWith(Order aggregate) {
        InMemoryOrderRepository repo = new InMemoryOrderRepository();
        repo.save(aggregate);
        return repo;
    }
}

final class InMemoryOrderRepository {
    private final java.util.Map<String,Order> store = new java.util.HashMap<>();
    void save(Order aggregate) { store.put(aggregate.id(), aggregate); }
}
record Order(String id) { }
record OrderRequest(String id, String type, java.math.BigDecimal amount) { }
⌂ Cockpit