Große Sammlung Java Enterprise Anti-Patterns und Architekturentscheidungen

121 konkrete Einträge: Architekturentscheidungen, Anti-Patterns, Refactoring-Zielcode, Maven/YAML/Java-Beispiele und SVG-Landkarten.

Enterprise Anti-Patterns Landkarte
0 Treffer
Architekturentscheidungen: Welche Technik passt wann?

Entscheidungen, die Senior-Entwickler in Reviews, Architekturboards und Modernisierungsprojekten treffen müssen.

Architekturentscheidungen: Welche Technik passt wann?

ap001: Architekturentscheidung: Spring Boot vs Jakarta EE vs Quarkus

Englischer technischer Begriff:
Framework Runtime Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Spring Boot vs Jakarta EE vs Quarkus in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Spring Boot vs Jakarta EE vs Quarkus wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class SpringBootVsJakartaEEVsQuarkusDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record SpringBootVsJakartaEEVsQuarkusPolicy(boolean async, Duration timeout, int maxRetries) {
    public static SpringBootVsJakartaEEVsQuarkusPolicy enterpriseDefault() {
        return new SpringBootVsJakartaEEVsQuarkusPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class SpringBootVsJakartaEEVsQuarkusUseCase {
    private final SpringBootVsJakartaEEVsQuarkusPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap002: Architekturentscheidung: REST vs SOAP vs Messaging

Englischer technischer Begriff:
Integration Style Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie REST vs SOAP vs Messaging in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu REST vs SOAP vs Messaging wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class PartnerPortalClient {
    public String submitOrder(Order order) {
        if (order.partner().usesSoap()) {
            return soapClient.call("SubmitOrder", order.toXml());
        }
        return http.post("/submitOrder", order).body();
    }
}
Ziel-Code
// Pattern: Strategy - Integrationsstil wird austauschbar und testbar.
public interface PartnerOrderGateway {
    SubmissionResult submit(Order order);
}
public final class SoapPartnerOrderGateway implements PartnerOrderGateway {
    public SubmissionResult submit(Order order) {
        return soapClient.submitOrder(order.toSoapContract());
    }
}
public final class RestPartnerOrderGateway implements PartnerOrderGateway {
    public SubmissionResult submit(Order order) {
        return http.postJson("/orders", OrderRequest.from(order));
    }
}

ap003: Architekturentscheidung: DTO vs Entity Exposure

Englischer technischer Begriff:
DTO Boundary Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie DTO vs Entity Exposure in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu DTO vs Entity Exposure wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class DTOVsEntityExposureDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record DTOVsEntityExposurePolicy(boolean async, Duration timeout, int maxRetries) {
    public static DTOVsEntityExposurePolicy enterpriseDefault() {
        return new DTOVsEntityExposurePolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class DTOVsEntityExposureUseCase {
    private final DTOVsEntityExposurePolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap004: Architekturentscheidung: Repository vs DAO vs Port

Englischer technischer Begriff:
Persistence Boundary Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Repository vs DAO vs Port in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Repository vs DAO vs Port wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class RepositoryVsDAOVsPortDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record RepositoryVsDAOVsPortPolicy(boolean async, Duration timeout, int maxRetries) {
    public static RepositoryVsDAOVsPortPolicy enterpriseDefault() {
        return new RepositoryVsDAOVsPortPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class RepositoryVsDAOVsPortUseCase {
    private final RepositoryVsDAOVsPortPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap005: Architekturentscheidung: Service Layer vs Use Case Layer

Englischer technischer Begriff:
Application Layer Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Service Layer vs Use Case Layer in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Service Layer vs Use Case Layer wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class ServiceLayerVsUseCaseLayerDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record ServiceLayerVsUseCaseLayerPolicy(boolean async, Duration timeout, int maxRetries) {
    public static ServiceLayerVsUseCaseLayerPolicy enterpriseDefault() {
        return new ServiceLayerVsUseCaseLayerPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class ServiceLayerVsUseCaseLayerUseCase {
    private final ServiceLayerVsUseCaseLayerPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap006: Architekturentscheidung: Synchronous HTTP vs Asynchronous Events

Englischer technischer Begriff:
Communication Mode Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Synchronous HTTP vs Asynchronous Events in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Synchronous HTTP vs Asynchronous Events wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class SynchronousHTTPVsAsynchronousEventsDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record SynchronousHTTPVsAsynchronousEventsPolicy(boolean async, Duration timeout, int maxRetries) {
    public static SynchronousHTTPVsAsynchronousEventsPolicy enterpriseDefault() {
        return new SynchronousHTTPVsAsynchronousEventsPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class SynchronousHTTPVsAsynchronousEventsUseCase {
    private final SynchronousHTTPVsAsynchronousEventsPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap007: Architekturentscheidung: Monolith Modularisieren vs Microservices

Englischer technischer Begriff:
Service Decomposition Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Monolith Modularisieren vs Microservices in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Monolith Modularisieren vs Microservices wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class MonolithModularisierenVsMicroservicesDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record MonolithModularisierenVsMicroservicesPolicy(boolean async, Duration timeout, int maxRetries) {
    public static MonolithModularisierenVsMicroservicesPolicy enterpriseDefault() {
        return new MonolithModularisierenVsMicroservicesPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class MonolithModularisierenVsMicroservicesUseCase {
    private final MonolithModularisierenVsMicroservicesPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap008: Architekturentscheidung: JPA vs JDBC vs Stored Procedure

Englischer technischer Begriff:
Data Access Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie JPA vs JDBC vs Stored Procedure in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu JPA vs JDBC vs Stored Procedure wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class JPAVsJDBCVsStoredProcedureDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record JPAVsJDBCVsStoredProcedurePolicy(boolean async, Duration timeout, int maxRetries) {
    public static JPAVsJDBCVsStoredProcedurePolicy enterpriseDefault() {
        return new JPAVsJDBCVsStoredProcedurePolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class JPAVsJDBCVsStoredProcedureUseCase {
    private final JPAVsJDBCVsStoredProcedurePolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap009: Architekturentscheidung: Virtual Threads vs ExecutorService

Englischer technischer Begriff:
Concurrency Model Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Virtual Threads vs ExecutorService in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Virtual Threads vs ExecutorService wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class ImportController {
    private final ExecutorService pool = Executors.newFixedThreadPool(400);
    public void start(List<URI> files) {
        files.forEach(uri -> pool.submit(() -> importFile(uri)));
    }
}
Ziel-Code
// Pattern: Bulkhead - begrenzter Zugriff auf externe Ressourcen.
public final class ImportExecutor {
    private final Semaphore databaseSlots = new Semaphore(30);
    public void importFiles(List<URI> files) throws InterruptedException {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            for (URI file : files) executor.submit(() -> importWithDatabaseLimit(file));
        }
    }
    private void importWithDatabaseLimit(URI file) throws Exception {
        if (!databaseSlots.tryAcquire(10, TimeUnit.SECONDS)) throw new TimeoutException("DB busy");
        try { importFile(file); } finally { databaseSlots.release(); }
    }
}

ap010: Architekturentscheidung: CompletableFuture vs Message Queue

Englischer technischer Begriff:
Async Processing Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie CompletableFuture vs Message Queue in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu CompletableFuture vs Message Queue wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class CompletableFutureVsMessageQueueDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record CompletableFutureVsMessageQueuePolicy(boolean async, Duration timeout, int maxRetries) {
    public static CompletableFutureVsMessageQueuePolicy enterpriseDefault() {
        return new CompletableFutureVsMessageQueuePolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class CompletableFutureVsMessageQueueUseCase {
    private final CompletableFutureVsMessageQueuePolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap011: Architekturentscheidung: BOM vs Parent POM

Englischer technischer Begriff:
Maven Dependency Governance Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie BOM vs Parent POM in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu BOM vs Parent POM wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.3.2</version></dependency>
  <dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.10.2</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Governance - Versionen zentral im BOM steuern. -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.acme.platform</groupId><artifactId>enterprise-platform-bom</artifactId><version>2026.07</version><type>pom</type><scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

ap012: Architekturentscheidung: Profiles vs Separate Pipelines

Englischer technischer Begriff:
Build Configuration Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Profiles vs Separate Pipelines in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Profiles vs Separate Pipelines wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class ProfilesVsSeparatePipelinesDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record ProfilesVsSeparatePipelinesPolicy(boolean async, Duration timeout, int maxRetries) {
    public static ProfilesVsSeparatePipelinesPolicy enterpriseDefault() {
        return new ProfilesVsSeparatePipelinesPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class ProfilesVsSeparatePipelinesUseCase {
    private final ProfilesVsSeparatePipelinesPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}

ap013: Architekturentscheidung: OpenShift Deployment vs Helm vs Kustomize

Englischer technischer Begriff:
Deployment Packaging Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie OpenShift Deployment vs Helm vs Kustomize in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu OpenShift Deployment vs Helm vs Kustomize wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
apiVersion: apps/v1
kind: Deployment
metadata: { name: order-service }
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: app
          image: latest
Ziel-Code
# Pattern: Release Template - Umgebung wird über Werte gesteuert.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: app
          image: registry.example.com/order-service:1.18.0
          readinessProbe: { httpGet: { path: /actuator/health/readiness, port: 8080 } }

ap014: Architekturentscheidung: JWT vs Session vs mTLS

Englischer technischer Begriff:
Authentication Boundary Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie JWT vs Session vs mTLS in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu JWT vs Session vs mTLS wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public boolean mayApprove(HttpServletRequest request) {
    return "ADMIN".equals(request.getHeader("X-Role"));
}
Ziel-Code
// Pattern: Policy Object - Berechtigung hängt an fachlicher Regel und geprüfter Identität.
public final class ApprovalPolicy {
    public boolean mayApprove(UserPrincipal user, Order order) {
        return user.hasScope("order:approve") && order.total().isLessThan(user.approvalLimit());
    }
}

ap015: Architekturentscheidung: Batch vs Stream Processing

Englischer technischer Begriff:
Processing Style Decision
Priorität:
8/10
Art:
Architekturentscheidung

Fachliche Situation: Ein Team muss entscheiden, wie Batch vs Stream Processing in einer Enterprise-Landschaft eingesetzt wird, ohne aus Gewohnheit zur falschen Technik zu greifen.

Technische Entscheidung: Die Entscheidung zu Batch vs Stream Processing wird als explizite Architekturregel mit Alternativen, Grenzen und Konsequenzen dokumentiert.

Warum wichtig: Die Entscheidung verhindert Architektur-Raten und macht Alternativen nachvollziehbar.

Typischer Fehler: Entscheidung wird über Bauchgefühl, Lieblingsframework oder vorhandenen Altcode getroffen.

Bessere Lösung: Entscheidung in ADR festhalten, Zielqualität messen und Code an klaren Ports oder Policies ausrichten.

Enterprise-Einordnung: Hilft bei Architekturboards, Migrationen, Plattform-Standards und nachvollziehbaren Technologieentscheidungen.

Ausgangspunkt-Code
public class BatchVsStreamProcessingDecision {
    public void execute(Order order) {
        if (System.getProperty("mode").equals("legacy")) legacyProcess(order);
        else modernProcess(order);
    }
}
Ziel-Code
// Pattern: Architecture Decision Record - Entscheidung wird explizit und testbar gemacht.
public record BatchVsStreamProcessingPolicy(boolean async, Duration timeout, int maxRetries) {
    public static BatchVsStreamProcessingPolicy enterpriseDefault() {
        return new BatchVsStreamProcessingPolicy(true, Duration.ofSeconds(3), 2);
    }
}
public final class BatchVsStreamProcessingUseCase {
    private final BatchVsStreamProcessingPolicy policy;
    public void execute(Order order) { validate(order); route(order, policy); }
}
Layering-, Service- und Clean-Architecture-Anti-Patterns

Typische Strukturfehler in großen Java-Enterprise-Anwendungen und bessere Zielarchitekturen.

Layering-, Service- und Clean-Architecture-Anti-Patterns

ap016: Anti-Pattern: God Service

Englischer technischer Begriff:
God Service Anti-Pattern
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt God Service häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: God Service wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class OrderService {
    public void checkout(HttpServletRequest request) throws SQLException, IOException {
        String customerNo = request.getParameter("customerNo");
        Connection c = dataSource.getConnection();
        c.prepareStatement("insert into orders(customer_no) values('" + customerNo + "')").execute();
        mail.send(customerNo, "created");
        http.post("https://billing.internal/invoice", request.getInputStream());
    }
}
Ziel-Code
// Pattern: Facade + Application Service - fachlicher Ablauf ohne Infrastrukturdetails.
public final class CheckoutUseCase {
    private final OrderRepository orders;
    private final BillingPort billing;
    private final CustomerNotificationPort notifications;
    public CheckoutResult checkout(CheckoutCommand command) {
        Order order = Order.createFor(command.customerNo(), command.lines());
        orders.save(order);
        billing.createInvoice(order.id());
        notifications.orderAccepted(order.customerNo(), order.id());
        return CheckoutResult.accepted(order.id());
    }
}

ap017: Anti-Pattern: Fat Controller

Englischer technischer Begriff:
Fat Controller Anti-Pattern
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Fat Controller häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Fat Controller wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@PostMapping("/orders/{id}/approve")
public ResponseEntity<?> approve(@PathVariable long id) {
    OrderEntity e = repository.findById(id).orElseThrow();
    if (e.getTotal().compareTo(new BigDecimal("10000")) > 0) e.setStatus("MANAGER_REVIEW");
    else e.setStatus("APPROVED");
    repository.save(e);
    return ResponseEntity.ok(e);
}
Ziel-Code
// Pattern: Use Case - Controller übersetzt nur HTTP in Anwendungssprache.
@PostMapping("/orders/{id}/approve")
public ResponseEntity<ApprovalResponse> approve(@PathVariable OrderId id) {
    return ResponseEntity.ok(approveOrder.approve(new ApproveOrderCommand(id)));
}
public final class ApproveOrderUseCase {
    public ApprovalResponse approve(ApproveOrderCommand command) {
        Order order = orders.get(command.orderId());
        order.approve(approvalPolicy);
        orders.save(order);
        return ApprovalResponse.from(order);
    }
}

ap018: Anti-Pattern: Anemic Domain Model

Englischer technischer Begriff:
Anemic Domain Model
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Anemic Domain Model häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Anemic Domain Model wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class OrderEntity {
    public BigDecimal total;
    public String status;
}
public class OrderWorkflow {
    public void approve(OrderEntity order) { order.status = "APPROVED"; }
}
Ziel-Code
// Pattern: Rich Domain Model - Invarianten liegen im Aggregat.
public final class Order {
    private OrderStatus status;
    private final Money total;
    public void approve(ApprovalPolicy policy) {
        if (!policy.canApprove(total)) throw new ApprovalDenied(total);
        this.status = OrderStatus.APPROVED;
    }
}

ap019: Anti-Pattern: Transaction Script

Englischer technischer Begriff:
Transaction Script
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Transaction Script häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Transaction Script wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class TransactionScriptService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class TransactionScriptUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap020: Anti-Pattern: Static Helper Hell

Englischer technischer Begriff:
Static Helper Hell
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Static Helper Hell häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Static Helper Hell wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class StaticHelperHellService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class StaticHelperHellUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap021: Anti-Pattern: Service Locator Missbrauch

Englischer technischer Begriff:
Service Locator Anti-Pattern
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Service Locator Missbrauch häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Service Locator Missbrauch wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ServiceLocatorMissbrauchService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class ServiceLocatorMissbrauchUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap022: Anti-Pattern: Hidden Coupling über Singleton

Englischer technischer Begriff:
Hidden Coupling Singleton
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Hidden Coupling über Singleton häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Hidden Coupling über Singleton wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class HiddenCouplingberSingletonService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class HiddenCouplingberSingletonUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap023: Anti-Pattern: Business Logic im Mapper

Englischer technischer Begriff:
Mapper Business Logic Anti-Pattern
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Business Logic im Mapper häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Business Logic im Mapper wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class BusinessLogicImMapperService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class BusinessLogicImMapperUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap024: Anti-Pattern: DTO Explosion

Englischer technischer Begriff:
DTO Explosion
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt DTO Explosion häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: DTO Explosion wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class DTOExplosionService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class DTOExplosionUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap025: Anti-Pattern: Package by Layer ohne Fachschnitt

Englischer technischer Begriff:
Layered Package Sprawl
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Package by Layer ohne Fachschnitt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Package by Layer ohne Fachschnitt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class PackageByLayerOhneFachschnittService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class PackageByLayerOhneFachschnittUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap026: Anti-Pattern: Controller kennt Datenbank

Englischer technischer Begriff:
Controller Database Coupling
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Controller kennt Datenbank häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Controller kennt Datenbank wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ControllerKenntDatenbankService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class ControllerKenntDatenbankUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap027: Anti-Pattern: Domain kennt HTTP

Englischer technischer Begriff:
Domain HTTP Coupling
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Domain kennt HTTP häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Domain kennt HTTP wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class DomainKenntHTTPService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class DomainKenntHTTPUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap028: Anti-Pattern: Utility-Klasse als Architektur

Englischer technischer Begriff:
Utility Class Architecture
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Utility-Klasse als Architektur häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Utility-Klasse als Architektur wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class UtilityKlasseAlsArchitekturService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class UtilityKlasseAlsArchitekturUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap029: Anti-Pattern: Zyklische Module

Englischer technischer Begriff:
Cyclic Module Dependency
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Zyklische Module häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Zyklische Module wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ZyklischeModuleService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class ZyklischeModuleUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}

ap030: Anti-Pattern: Keine Ports und Adapter

Englischer technischer Begriff:
Missing Ports and Adapters
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Keine Ports und Adapter häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Der Schnitt trennt Fachlogik, Infrastruktur und API-Vertrag dauerhaft.

Typischer Fehler: Keine Ports und Adapter wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class KeinePortsUndAdapterService {
    public Object handle(Map<String,Object> payload) {
        String orderNo = (String) payload.get("orderNo");
        jdbc.update("update orders set status='DONE' where order_no='" + orderNo + "'");
        return payload;
    }
}
Ziel-Code
// Pattern: Ports and Adapters - fachliche Logik kennt keine Infrastruktur.
public final class KeinePortsUndAdapterUseCase {
    private final OrderRepository orders;
    private final AuditPort audit;
    public OrderResult handle(OrderCommand command) {
        Order order = orders.get(command.orderNo());
        order.markProcessed();
        orders.save(order);
        audit.record("ORDER_PROCESSED", order.orderNo().value());
        return OrderResult.from(order);
    }
}
Persistenz-, Daten- und Transaktions-Anti-Patterns

Fehler rund um JPA, JDBC, Transaktionen, Datenmodell und Konsistenz.

Persistenz-, Daten- und Transaktions-Anti-Patterns

ap031: Anti-Pattern: N+1 Query

Englischer technischer Begriff:
N+1 Query Anti-Pattern
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt N+1 Query häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: N+1 Query wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
List<OrderEntity> orders = em.createQuery("select o from OrderEntity o", OrderEntity.class).getResultList();
for (OrderEntity order : orders) {
    System.out.println(order.getLines().size()); // löst je Order eine weitere Query aus
}
Ziel-Code
// Pattern: Query Object - benötigte Daten werden bewusst geladen.
String jpql = "select new com.acme.OrderSummary(o.id, o.orderNo, count(l.id)) "
    + "from OrderEntity o left join o.lines l "
    + "group by o.id, o.orderNo";
List<OrderSummary> orders = em.createQuery(jpql, OrderSummary.class)
    .setMaxResults(200)
    .getResultList();

ap032: Anti-Pattern: Open Session in View

Englischer technischer Begriff:
Open Session in View
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Open Session in View häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Open Session in View wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap033: Anti-Pattern: Lazy Loading im JSON

Englischer technischer Begriff:
Lazy Loading Serialization Trap
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Lazy Loading im JSON häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Lazy Loading im JSON wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap034: Anti-Pattern: Entity direkt als API-Vertrag

Englischer technischer Begriff:
Entity as API Contract
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Entity direkt als API-Vertrag häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Entity direkt als API-Vertrag wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap035: Anti-Pattern: Mega-Repository

Englischer technischer Begriff:
Mega Repository
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Mega-Repository häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Mega-Repository wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap036: Anti-Pattern: Unbegrenzte Abfragen

Englischer technischer Begriff:
Unbounded Query
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Unbegrenzte Abfragen häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Unbegrenzte Abfragen wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap037: Anti-Pattern: Transaktion über Remote Calls

Englischer technischer Begriff:
Remote Call inside Transaction
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Transaktion über Remote Calls häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Transaktion über Remote Calls wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@Transactional
public void approve(String orderNo) {
    OrderEntity order = repository.get(orderNo);
    partnerClient.reserve(orderNo); // Remote Call hält DB-Transaktion offen
    order.setStatus("APPROVED");
}
Ziel-Code
// Pattern: Transactional Outbox - DB-Transaktion und Integration entkoppeln.
@Transactional
public void approve(String orderNo) {
    Order order = orders.get(orderNo);
    order.approve();
    orders.save(order);
    outbox.add(new PartnerReservationRequested(orderNo, order.version()));
}

ap038: Anti-Pattern: Read/Write ohne Optimistic Locking

Englischer technischer Begriff:
Missing Optimistic Locking
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Read/Write ohne Optimistic Locking häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Read/Write ohne Optimistic Locking wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@Entity
public class OrderEntity {
    @Id Long id;
    String status;
}
Ziel-Code
// Pattern: Optimistic Locking - parallele Änderungen werden erkannt.
@Entity
public class OrderEntity {
    @Id Long id;
    @Version long version;
    @Enumerated(EnumType.STRING) OrderStatus status;
}

ap039: Anti-Pattern: Datenbank als Message Queue

Englischer technischer Begriff:
Database as Queue
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Datenbank als Message Queue häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Datenbank als Message Queue wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap040: Anti-Pattern: Stored Procedure Wildwuchs

Englischer technischer Begriff:
Stored Procedure Sprawl
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Stored Procedure Wildwuchs häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Stored Procedure Wildwuchs wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap041: Anti-Pattern: Audit nur im Logfile

Englischer technischer Begriff:
Log-only Audit
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Audit nur im Logfile häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Audit nur im Logfile wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap042: Anti-Pattern: Sensible Daten unmaskiert

Englischer technischer Begriff:
Unmasked Sensitive Data
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Sensible Daten unmaskiert häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Sensible Daten unmaskiert wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap043: Anti-Pattern: Migration ohne Versionierung

Englischer technischer Begriff:
Unversioned Schema Migration
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Migration ohne Versionierung häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Migration ohne Versionierung wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap044: Anti-Pattern: Batch ohne Checkpoint

Englischer technischer Begriff:
Missing Batch Checkpoint
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Batch ohne Checkpoint häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Batch ohne Checkpoint wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}

ap045: Anti-Pattern: Fachstatus als String-Salat

Englischer technischer Begriff:
Stringly Typed Status
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Fachstatus als String-Salat häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Datenzugriff bleibt kontrollierbar, testbar und transaktionssicher.

Typischer Fehler: Fachstatus als String-Salat wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public List<OrderEntity> loadOrders(String status) {
    return em.createQuery("select o from OrderEntity o where o.status='" + status + "'", OrderEntity.class)
             .getResultList();
}
Ziel-Code
// Pattern: Repository + Specification - Abfrage ist begrenzt und typisiert.
public Page<OrderProjection> findOrders(OrderSearchCriteria criteria, PageRequest page) {
    return orderRepository.findByStatusAndCreatedAfter(
        criteria.status(), criteria.from(), page.limit(100));
}
API-, Integration- und Event-Driven-Anti-Patterns

Fehler bei REST, SOAP, Events, Outbox, Partner-Portalen und Systemkopplung.

API-, Integration- und Event-Driven-Anti-Patterns

ap046: Anti-Pattern: Chatty REST API

Englischer technischer Begriff:
Chatty API Anti-Pattern
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Chatty REST API häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Chatty REST API wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ChattyRESTAPIClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class ChattyRESTAPIPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap047: Anti-Pattern: REST als RPC missbraucht

Englischer technischer Begriff:
RPC over REST Anti-Pattern
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt REST als RPC missbraucht häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: REST als RPC missbraucht wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class RESTAlsRPCMissbrauchtClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class RESTAlsRPCMissbrauchtPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap048: Anti-Pattern: SOAP Vertrag ohne Kompatibilität

Englischer technischer Begriff:
Breaking SOAP Contract
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt SOAP Vertrag ohne Kompatibilität häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: SOAP Vertrag ohne Kompatibilität wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class SOAPVertragOhneKompatibilittClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class SOAPVertragOhneKompatibilittPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap049: Anti-Pattern: Gemeinsame DTO-Bibliothek zwischen Systemen

Englischer technischer Begriff:
Shared DTO Coupling
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Gemeinsame DTO-Bibliothek zwischen Systemen häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Gemeinsame DTO-Bibliothek zwischen Systemen wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class GemeinsameDTOBibliothekZwischenSystemenClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class GemeinsameDTOBibliothekZwischenSystemenPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap050: Anti-Pattern: Schnittstelle ohne Idempotenz

Englischer technischer Begriff:
Missing Idempotency
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Schnittstelle ohne Idempotenz häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Schnittstelle ohne Idempotenz wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@PostMapping("/payments")
public PaymentResult pay(@RequestBody PaymentCommand command) {
    return paymentService.charge(command.orderNo(), command.amount());
}
Ziel-Code
// Pattern: Idempotency Key - Wiederholungen erzeugen keine Doppelbuchung.
@PostMapping("/payments")
public PaymentResult pay(@RequestHeader("Idempotency-Key") String key,
                         @RequestBody PaymentCommand command) {
    return paymentService.chargeOnce(key, command.orderNo(), command.amount());
}

ap051: Anti-Pattern: Event ohne Schema-Version

Englischer technischer Begriff:
Unversioned Event Schema
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Event ohne Schema-Version häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Event ohne Schema-Version wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class EventOhneSchemaVersionClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class EventOhneSchemaVersionPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap052: Anti-Pattern: Outbox vergessen

Englischer technischer Begriff:
Missing Transactional Outbox
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Outbox vergessen häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Outbox vergessen wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@Transactional
public void create(Order order) {
    orderRepository.save(order);
    kafka.send("orders", new OrderCreated(order.id())); // kann nach Commit verloren gehen
}
Ziel-Code
// Pattern: Transactional Outbox - Event wird atomar mit dem Aggregat gespeichert.
@Transactional
public void create(Order order) {
    orderRepository.save(order);
    outboxRepository.append(new OutboxEvent("OrderCreated", order.id().value(), order.toEventJson()));
}
public void publishPending() {
    outboxRepository.lockNextBatch(100).forEach(event -> kafka.send(event.topic(), event.key(), event.payload()));
}

ap053: Anti-Pattern: Exactly Once Illusion

Englischer technischer Begriff:
Exactly Once Illusion
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Exactly Once Illusion häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Exactly Once Illusion wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ExactlyOnceIllusionClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class ExactlyOnceIllusionPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap054: Anti-Pattern: Kafka Topic als Datenbank

Englischer technischer Begriff:
Log as Database Misuse
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Kafka Topic als Datenbank häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Kafka Topic als Datenbank wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class KafkaTopicAlsDatenbankClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class KafkaTopicAlsDatenbankPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap055: Anti-Pattern: Retry ohne Backoff

Englischer technischer Begriff:
Retry Storm
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Retry ohne Backoff häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Retry ohne Backoff wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
for (int i = 0; i < 20; i++) {
    try { return partnerClient.call(request); }
    catch (IOException ex) { /* sofort wiederholen */ }
}
throw new PartnerUnavailable();
Ziel-Code
// Pattern: Retry with Backoff - Wiederholung schützt statt Lastspitzen zu erzeugen.
RetryPolicy policy = RetryPolicy.builder()
    .maxAttempts(3)
    .delay(Duration.ofMillis(200))
    .jitter(Duration.ofMillis(100))
    .retryOn(IOException.class)
    .build();
return retry.execute(policy, () -> partnerClient.call(request));

ap056: Anti-Pattern: Timeout fehlt

Englischer technischer Begriff:
Missing Timeout
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Timeout fehlt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Timeout fehlt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
HttpRequest request = HttpRequest.newBuilder(endpoint.resolve("/price"))
    .POST(BodyPublishers.ofString(json))
    .build();
return http.send(request, BodyHandlers.ofString()).body();
Ziel-Code
// Pattern: Timeout Budget - jeder externe Aufruf hat eine klare Obergrenze.
HttpRequest request = HttpRequest.newBuilder(endpoint.resolve("/price"))
    .timeout(Duration.ofSeconds(2))
    .POST(BodyPublishers.ofString(json))
    .build();
return http.send(request, BodyHandlers.ofString()).body();

ap057: Anti-Pattern: Circuit Breaker fehlt

Englischer technischer Begriff:
Missing Circuit Breaker
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Circuit Breaker fehlt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Circuit Breaker fehlt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class CircuitBreakerFehltClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class CircuitBreakerFehltPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap058: Anti-Pattern: Partner-System direkt im Domain-Service

Englischer technischer Begriff:
External System in Domain Service
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Partner-System direkt im Domain-Service häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Partner-System direkt im Domain-Service wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class PartnerSystemDirektImDomainServiceClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class PartnerSystemDirektImDomainServicePartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap059: Anti-Pattern: API ohne Correlation-ID

Englischer technischer Begriff:
Missing Correlation ID
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt API ohne Correlation-ID häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: API ohne Correlation-ID wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class APIOhneCorrelationIDClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class APIOhneCorrelationIDPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}

ap060: Anti-Pattern: Upload ohne Größenlimit

Englischer technischer Begriff:
Unbounded Upload
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Upload ohne Größenlimit häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Systemgrenzen bleiben stabil, kompatibel und fehlertolerant.

Typischer Fehler: Upload ohne Größenlimit wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class UploadOhneGrssenlimitClient {
    public void send(Order order) {
        http.post("/partner", order.toString());
    }
}
Ziel-Code
// Pattern: Adapter + Contract - externer Vertrag ist versioniert und isoliert.
public final class UploadOhneGrssenlimitPartnerAdapter implements PartnerPort {
    public PartnerResult send(Order order) {
        PartnerOrderV2 request = PartnerOrderV2.from(order);
        return PartnerResult.from(http.postJson("/api/v2/orders", request));
    }
}
Security-, Datei-, HTTP- und Compliance-Anti-Patterns

Sicherheitsfehler bei Dateioperationen, HTTP, Secrets, Rollen, Serialisierung und Auditierbarkeit.

Security-, Datei-, HTTP- und Compliance-Anti-Patterns

ap061: Anti-Pattern: Path Traversal bei Downloads

Englischer technischer Begriff:
Path Traversal
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Path Traversal bei Downloads häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Path Traversal bei Downloads wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public Path download(String fileName) {
    return Paths.get("/srv/contracts/" + fileName);
}
Ziel-Code
// Pattern: Input Validation - Pfad bleibt innerhalb des erlaubten Verzeichnisses.
public Path download(String fileName) {
    Path base = Paths.get("/srv/contracts").toAbsolutePath().normalize();
    Path resolved = base.resolve(fileName).normalize();
    if (!resolved.startsWith(base)) throw new AccessDeniedException(fileName);
    return resolved;
}

ap062: Anti-Pattern: Unsichere Java-Serialization

Englischer technischer Begriff:
Unsafe Java Serialization
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Unsichere Java-Serialization häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Unsichere Java-Serialization wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
try (ObjectInputStream in = new ObjectInputStream(request.getInputStream())) {
    ImportCommand command = (ImportCommand) in.readObject();
    importService.run(command);
}
Ziel-Code
// Pattern: Explicit Contract - JSON DTO statt unsicherer Objektserialisierung.
ImportCommandDto dto = objectMapper.readValue(request.getInputStream(), ImportCommandDto.class);
validator.validate(dto);
importService.run(dto.toCommand());

ap063: Anti-Pattern: XML External Entity

Englischer technischer Begriff:
XXE Vulnerability
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt XML External Entity häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: XML External Entity wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(xmlInputStream);
Ziel-Code
// Pattern: Secure Parser Configuration - externe Entitäten sind deaktiviert.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setExpandEntityReferences(false);
Document doc = factory.newDocumentBuilder().parse(xmlInputStream);

ap064: Anti-Pattern: CSV Injection

Englischer technischer Begriff:
CSV Formula Injection
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt CSV Injection häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: CSV Injection wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
writer.println(customer.name() + "," + customer.comment());
Ziel-Code
// Pattern: Output Encoding - Tabellenprogramme interpretieren keine Formeln.
String safeComment = customer.comment().replaceAll("^([=+\-@])", "'$1");
writer.printf("%s,%s%n", csv.escape(customer.name()), csv.escape(safeComment));

ap065: Anti-Pattern: Secrets im Git Repository

Englischer technischer Begriff:
Secrets in Source Control
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Secrets im Git Repository häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Secrets im Git Repository wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class SecretsImGitRepositoryPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap066: Anti-Pattern: Admin-Rolle als String-Vergleich

Englischer technischer Begriff:
String Role Check
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Admin-Rolle als String-Vergleich häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Admin-Rolle als String-Vergleich wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class AdminRolleAlsStringVergleichPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap067: Anti-Pattern: Fehlende Output-Encoding

Englischer technischer Begriff:
Missing Output Encoding
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Fehlende Output-Encoding häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Fehlende Output-Encoding wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class FehlendeOutputEncodingPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap068: Anti-Pattern: Unvalidierte Redirect-URL

Englischer technischer Begriff:
Open Redirect
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Unvalidierte Redirect-URL häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Unvalidierte Redirect-URL wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class UnvalidierteRedirectURLPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap069: Anti-Pattern: Upload ohne Content-Prüfung

Englischer technischer Begriff:
Unsafe File Upload
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Upload ohne Content-Prüfung häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Upload ohne Content-Prüfung wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class UploadOhneContentPrfungPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap070: Anti-Pattern: Fehlende Rate Limits

Englischer technischer Begriff:
Missing Rate Limiting
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Fehlende Rate Limits häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Fehlende Rate Limits wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class FehlendeRateLimitsPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap071: Anti-Pattern: Security nur im Controller

Englischer technischer Begriff:
Controller-only Security
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Security nur im Controller häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Security nur im Controller wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class SecurityNurImControllerPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap072: Anti-Pattern: Audit ohne Fachkontext

Englischer technischer Begriff:
Context-free Audit
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Audit ohne Fachkontext häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Audit ohne Fachkontext wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class AuditOhneFachkontextPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap073: Anti-Pattern: Persönliche Daten im Log

Englischer technischer Begriff:
PII in Logs
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Persönliche Daten im Log häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: Persönliche Daten im Log wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class PersnlicheDatenImLogPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap074: Anti-Pattern: CORS Wildcard im Enterprise

Englischer technischer Begriff:
Wildcard CORS
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt CORS Wildcard im Enterprise häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: CORS Wildcard im Enterprise wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class CORSWildcardImEnterprisePolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}

ap075: Anti-Pattern: TLS Zertifikatsprüfung deaktiviert

Englischer technischer Begriff:
Disabled TLS Verification
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt TLS Zertifikatsprüfung deaktiviert häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Angriffsfläche, Datenschutz- und Compliance-Risiken werden reduziert.

Typischer Fehler: TLS Zertifikatsprüfung deaktiviert wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public boolean allowed(String role) {
    return role.equals("ADMIN");
}
Ziel-Code
// Pattern: Policy Object - Berechtigung ist fachlich und zentral prüfbar.
public final class TLSZertifikatsprfungDeaktiviertPolicy {
    public boolean allowed(UserPrincipal user, BusinessAction action) {
        return user.hasPermission(action.requiredPermission()) && user.tenant().equals(action.tenant());
    }
}
Concurrency-, Performance- und Resilience-Anti-Patterns

Fehler bei Threads, Locks, Async-APIs, Backpressure, Caches, Pools und Lastspitzen.

Concurrency-, Performance- und Resilience-Anti-Patterns

ap076: Anti-Pattern: Unbegrenzter Thread-Pool

Englischer technischer Begriff:
Unbounded Thread Pool
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Unbegrenzter Thread-Pool häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Unbegrenzter Thread-Pool wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
ExecutorService executor = Executors.newCachedThreadPool();
for (ImportJob job : jobs) {
    executor.submit(() -> importService.run(job));
}
Ziel-Code
// Pattern: Bulkhead - Parallelität wird pro Ressource begrenzt.
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    8, 32, 30, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(500),
    new ThreadPoolExecutor.CallerRunsPolicy());
jobs.forEach(job -> executor.submit(() -> importService.run(job)));

ap077: Anti-Pattern: parallelStream in Enterprise Services

Englischer technischer Begriff:
parallelStream Misuse
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt parallelStream in Enterprise Services häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: parallelStream in Enterprise Services wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ParallelStreamInEnterpriseServicesCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class ParallelStreamInEnterpriseServicesCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap078: Anti-Pattern: CompletableFuture ohne Executor

Englischer technischer Begriff:
Common Pool Trap
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt CompletableFuture ohne Executor häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: CompletableFuture ohne Executor wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
CompletableFuture<OrderView> view = CompletableFuture.supplyAsync(() -> loadOrder(orderNo))
    .thenCombine(CompletableFuture.supplyAsync(() -> loadInvoice(orderNo)), OrderView::new);
Ziel-Code
// Pattern: Dedicated Executor - blockierende IO-Arbeit nutzt einen eigenen Pool.
ExecutorService ioExecutor = Executors.newFixedThreadPool(24);
CompletableFuture<Order> order = CompletableFuture.supplyAsync(() -> loadOrder(orderNo), ioExecutor);
CompletableFuture<Invoice> invoice = CompletableFuture.supplyAsync(() -> loadInvoice(orderNo), ioExecutor);
OrderView view = order.thenCombine(invoice, OrderView::new).orTimeout(2, TimeUnit.SECONDS).join();

ap079: Anti-Pattern: Future.get ohne Timeout

Englischer technischer Begriff:
Blocking Future without Timeout
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Future.get ohne Timeout häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Future.get ohne Timeout wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class FutureGetOhneTimeoutCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class FutureGetOhneTimeoutCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap080: Anti-Pattern: ThreadLocal Leak

Englischer technischer Begriff:
ThreadLocal Memory Leak
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt ThreadLocal Leak häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: ThreadLocal Leak wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public final class TenantContext {
    static final ThreadLocal<String> TENANT = new ThreadLocal<>();
    public static void set(String tenant) { TENANT.set(tenant); }
}
Ziel-Code
// Pattern: Scoped Context - Kontext wird übergeben und sicher geschlossen.
try (TenantScope ignored = tenantContext.open(request.tenant())) {
    orderUseCase.execute(command);
}
public void close() { currentTenant.remove(); }

ap081: Anti-Pattern: volatile als Lock-Ersatz

Englischer technischer Begriff:
Volatile as Lock Substitute
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt volatile als Lock-Ersatz häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: volatile als Lock-Ersatz wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class VolatileAlsLockErsatzCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class VolatileAlsLockErsatzCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap082: Anti-Pattern: Atomic ohne Invariantenschutz

Englischer technischer Begriff:
Broken Atomic Invariant
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Atomic ohne Invariantenschutz häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Atomic ohne Invariantenschutz wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class AtomicOhneInvariantenschutzCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class AtomicOhneInvariantenschutzCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap083: Anti-Pattern: BlockingQueue ohne Backpressure

Englischer technischer Begriff:
Missing Backpressure
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt BlockingQueue ohne Backpressure häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: BlockingQueue ohne Backpressure wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
BlockingQueue<Event> queue = new LinkedBlockingQueue<>();
public void publish(Event event) { queue.add(event); }
Ziel-Code
// Pattern: Backpressure - Queue ist begrenzt und Überlast wird sichtbar.
BlockingQueue<Event> queue = new ArrayBlockingQueue<>(10_000);
public boolean publish(Event event) throws InterruptedException {
    return queue.offer(event, 250, TimeUnit.MILLISECONDS);
}

ap084: Anti-Pattern: Cache ohne Eviction

Englischer technischer Begriff:
Unbounded Cache
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Cache ohne Eviction häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Cache ohne Eviction wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class CacheOhneEvictionCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class CacheOhneEvictionCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap085: Anti-Pattern: Synchronized auf Remote Call

Englischer technischer Begriff:
Lock around Remote Call
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Synchronized auf Remote Call häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Synchronized auf Remote Call wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class SynchronizedAufRemoteCallCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class SynchronizedAufRemoteCallCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap086: Anti-Pattern: Virtuelle Threads für CPU-Arbeit

Englischer technischer Begriff:
Virtual Threads CPU Misuse
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Virtuelle Threads für CPU-Arbeit häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Virtuelle Threads für CPU-Arbeit wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class VirtuelleThreadsFrCPUArbeitCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class VirtuelleThreadsFrCPUArbeitCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap087: Anti-Pattern: Connection Pool größer als Datenbank

Englischer technischer Begriff:
Oversized Connection Pool
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Connection Pool größer als Datenbank häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Connection Pool größer als Datenbank wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ConnectionPoolGrsserAlsDatenbankCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class ConnectionPoolGrsserAlsDatenbankCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap088: Anti-Pattern: Retry plus Thread-Pool Erschöpfung

Englischer technischer Begriff:
Retry Pool Exhaustion
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Retry plus Thread-Pool Erschöpfung häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Retry plus Thread-Pool Erschöpfung wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class RetryPlusThreadPoolErschpfungCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class RetryPlusThreadPoolErschpfungCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap089: Anti-Pattern: Bulkhead fehlt

Englischer technischer Begriff:
Missing Bulkhead
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Bulkhead fehlt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Bulkhead fehlt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class BulkheadFehltCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class BulkheadFehltCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}

ap090: Anti-Pattern: Concurrent Test ohne Determinismus

Englischer technischer Begriff:
Non-deterministic Concurrent Test
Priorität:
9/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Concurrent Test ohne Determinismus häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Parallelität wird begrenzt, messbar und reproduzierbar testbar.

Typischer Fehler: Concurrent Test ohne Determinismus wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ConcurrentTestOhneDeterminismusCache {
    private final Map<String, Order> cache = new HashMap<>();
    public Order get(String key) { return cache.computeIfAbsent(key, this::load); }
}
Ziel-Code
// Pattern: Thread-safe Cache - Nebenläufigkeit und Begrenzung sind explizit.
public final class ConcurrentTestOhneDeterminismusCache {
    private final ConcurrentMap<String, CompletableFuture<Order>> cache = new ConcurrentHashMap<>();
    public Order get(String key) {
        return cache.computeIfAbsent(key, k -> CompletableFuture.supplyAsync(() -> load(k)))
                    .orTimeout(1, TimeUnit.SECONDS).join();
    }
}
Maven-, Build-, Dependency- und Release-Anti-Patterns

Fehler in POM-Struktur, Dependencies, Plugin-Versionen, Profilen und Supply-Chain-Governance.

Maven-, Build-, Dependency- und Release-Anti-Patterns

ap091: Anti-Pattern: Dependency-Versionen überall verstreut

Englischer technischer Begriff:
Scattered Dependency Versions
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Dependency-Versionen überall verstreut häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Dependency-Versionen überall verstreut wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap092: Anti-Pattern: Plugin-Versionen nicht fixiert

Englischer technischer Begriff:
Unpinned Plugin Versions
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Plugin-Versionen nicht fixiert häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Plugin-Versionen nicht fixiert wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<build>
  <plugins>
    <plugin><artifactId>maven-compiler-plugin</artifactId></plugin>
  </plugins>
</build>
Ziel-Code
<!-- Pattern: Reproducible Build - Plugin-Versionen sind festgelegt. -->
<pluginManagement>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.13.0</version>
      <configuration><release>21</release></configuration>
    </plugin>
  </plugins>
</pluginManagement>

ap093: Anti-Pattern: Snapshot in Produktion

Englischer technischer Begriff:
Snapshot in Production
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Snapshot in Produktion häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Snapshot in Produktion wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependency>
  <groupId>com.acme</groupId><artifactId>pricing-client</artifactId><version>2.4-SNAPSHOT</version>
</dependency>
Ziel-Code
<!-- Pattern: Release Governance - produktive Abhängigkeiten sind unveränderlich. -->
<dependency>
  <groupId>com.acme</groupId><artifactId>pricing-client</artifactId><version>${pricing-client.version}</version>
</dependency>
<properties><pricing-client.version>2.4.3</pricing-client.version></properties>

ap094: Anti-Pattern: Transitive Dependencies ungeprüft

Englischer technischer Begriff:
Uncontrolled Transitive Dependencies
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Transitive Dependencies ungeprüft häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Transitive Dependencies ungeprüft wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap095: Anti-Pattern: Profiles als Environment-Logik

Englischer technischer Begriff:
Profile Environment Logic
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Profiles als Environment-Logik häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Profiles als Environment-Logik wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap096: Anti-Pattern: Parent POM als Müllschublade

Englischer technischer Begriff:
Parent POM Dumping Ground
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Parent POM als Müllschublade häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Parent POM als Müllschublade wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap097: Anti-Pattern: BOM ohne klare Verantwortung

Englischer technischer Begriff:
Unowned BOM
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt BOM ohne klare Verantwortung häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: BOM ohne klare Verantwortung wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap098: Anti-Pattern: Multi-Modul ohne fachliche Grenzen

Englischer technischer Begriff:
Module Sprawl
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Multi-Modul ohne fachliche Grenzen häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Multi-Modul ohne fachliche Grenzen wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap099: Anti-Pattern: Build erzeugt nicht reproduzierbare Artefakte

Englischer technischer Begriff:
Non-reproducible Build
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Build erzeugt nicht reproduzierbare Artefakte häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Build erzeugt nicht reproduzierbare Artefakte wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap100: Anti-Pattern: Tests per Default übersprungen

Englischer technischer Begriff:
Skipped Tests by Default
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Tests per Default übersprungen häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Tests per Default übersprungen wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap101: Anti-Pattern: Shade Plugin ohne Relocation

Englischer technischer Begriff:
Unsafe Shading
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Shade Plugin ohne Relocation häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Shade Plugin ohne Relocation wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<build>
  <plugins>
    <plugin><artifactId>maven-compiler-plugin</artifactId></plugin>
  </plugins>
</build>
Ziel-Code
<!-- Pattern: Reproducible Build - Plugin-Versionen sind festgelegt. -->
<pluginManagement>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.13.0</version>
      <configuration><release>21</release></configuration>
    </plugin>
  </plugins>
</pluginManagement>

ap102: Anti-Pattern: Versions-Mismatch Java und Compiler

Englischer technischer Begriff:
Compiler Runtime Mismatch
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Versions-Mismatch Java und Compiler häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Versions-Mismatch Java und Compiler wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap103: Anti-Pattern: Repository Credentials im POM

Englischer technischer Begriff:
Credentials in POM
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Repository Credentials im POM häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Repository Credentials im POM wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<repository>
  <id>company</id><url>https://repo.example.com</url>
</repository>
<properties><repo.password>secret123</repo.password></properties>
Ziel-Code
<!-- Pattern: Secret Externalization - Zugangsdaten liegen in settings.xml oder Secret Store. -->
<repository>
  <id>company-releases</id>
  <url>https://repo.example.com/releases</url>
</repository>
<!-- settings.xml enthält server credentials für company-releases. -->

ap104: Anti-Pattern: Maven Wrapper fehlt

Englischer technischer Begriff:
Missing Maven Wrapper
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Maven Wrapper fehlt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Maven Wrapper fehlt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>

ap105: Anti-Pattern: Dependency-Konflikt wird ignoriert

Englischer technischer Begriff:
Ignored Dependency Convergence
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Dependency-Konflikt wird ignoriert häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Builds bleiben reproduzierbar, auditierbar und teamweit konsistent.

Typischer Fehler: Dependency-Konflikt wird ignoriert wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
<dependencies>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.0</version></dependency>
  <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.1</version></dependency>
</dependencies>
Ziel-Code
<!-- Pattern: Dependency Convergence - Versionen werden zentral geprüft. -->
<dependencyManagement>
  <dependencies>
    <dependency><groupId>com.fasterxml.jackson</groupId><artifactId>jackson-bom</artifactId><version>2.17.2</version><type>pom</type><scope>import</scope></dependency>
  </dependencies>
</dependencyManagement>
Testing-, Observability-, Betrieb- und Modernisierungs-Anti-Patterns

Anti-Patterns, die erst in Produktion, Migration oder Betrieb sichtbar werden.

Testing-, Observability-, Betrieb- und Modernisierungs-Anti-Patterns

ap106: Anti-Pattern: Testpyramide umgedreht

Englischer technischer Begriff:
Inverted Test Pyramid
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Testpyramide umgedreht häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Testpyramide umgedreht wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class TestpyramideUmgedrehtTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class TestpyramideUmgedrehtTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap107: Anti-Pattern: Nur Happy-Path Tests

Englischer technischer Begriff:
Happy Path Testing
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Nur Happy-Path Tests häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Nur Happy-Path Tests wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class NurHappyPathTestsTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class NurHappyPathTestsTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap108: Anti-Pattern: Mocking der eigenen Domäne

Englischer technischer Begriff:
Domain Overmocking
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Mocking der eigenen Domäne häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Mocking der eigenen Domäne wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class MockingDerEigenenDomneTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class MockingDerEigenenDomneTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap109: Anti-Pattern: Integrationstest ohne Testcontainers

Englischer technischer Begriff:
Fake Integration Test
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Integrationstest ohne Testcontainers häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Integrationstest ohne Testcontainers wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class IntegrationstestOhneTestcontainersTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class IntegrationstestOhneTestcontainersTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap110: Anti-Pattern: Fehlende Contract Tests

Englischer technischer Begriff:
Missing Contract Tests
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Fehlende Contract Tests häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Fehlende Contract Tests wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class FehlendeContractTestsTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class FehlendeContractTestsTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap111: Anti-Pattern: Logs ohne Korrelation

Englischer technischer Begriff:
Uncorrelated Logs
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Logs ohne Korrelation häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Logs ohne Korrelation wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
log.info("Order approved");
partnerClient.notify(orderNo);
Ziel-Code
// Pattern: Correlation ID - Logs und Partneraufrufe sind zusammenführbar.
try (var ignored = MDC.putCloseable("correlationId", command.correlationId())) {
    log.info("order approved orderNo={}", orderNo);
    partnerClient.notify(orderNo, command.correlationId());
}

ap112: Anti-Pattern: Metriken ohne Fachbezug

Englischer technischer Begriff:
Technical-only Metrics
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Metriken ohne Fachbezug häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Metriken ohne Fachbezug wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class MetrikenOhneFachbezugTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class MetrikenOhneFachbezugTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap113: Anti-Pattern: Health Check prüft nichts

Englischer technischer Begriff:
Shallow Health Check
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Health Check prüft nichts häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Health Check prüft nichts wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
@GetMapping("/health")
public String health() { return "OK"; }
Ziel-Code
// Pattern: Health Probe - Readiness prüft abhängige Ressourcen mit Timeout.
@Readiness
public HealthCheckResponse readiness() {
    boolean databaseReady = database.ping(Duration.ofMillis(500));
    return databaseReady ? HealthCheckResponse.up("database") : HealthCheckResponse.down("database");
}

ap114: Anti-Pattern: Feature Toggle ohne Ablaufdatum

Englischer technischer Begriff:
Permanent Feature Toggle
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Feature Toggle ohne Ablaufdatum häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Feature Toggle ohne Ablaufdatum wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class FeatureToggleOhneAblaufdatumTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class FeatureToggleOhneAblaufdatumTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap115: Anti-Pattern: Big Bang Migration

Englischer technischer Begriff:
Big Bang Migration
Priorität:
10/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Big Bang Migration häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Big Bang Migration wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class BigBangMigrationTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class BigBangMigrationTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap116: Anti-Pattern: Strangler ohne Rückbauplan

Englischer technischer Begriff:
Strangler without Retirement Plan
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Strangler ohne Rückbauplan häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Strangler ohne Rückbauplan wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class StranglerOhneRckbauplanTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class StranglerOhneRckbauplanTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap117: Anti-Pattern: Keine ADRs

Englischer technischer Begriff:
Missing Architecture Decision Records
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Keine ADRs häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Keine ADRs wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
// Entscheidung aus Meeting: wir nehmen Events.
public void place(Order order) {
    eventBus.publish(order.toEvent());
}
Ziel-Code
// Pattern: Architecture Decision Record - Code verweist auf dokumentierte Entscheidung.
// ADR-004: Orders publishen Domain Events über Outbox, nicht direkt über Kafka.
@Transactional
public void place(Order order) {
    orders.save(order);
    outbox.append(OrderPlacedV1.from(order));
}

ap118: Anti-Pattern: Runbook fehlt

Englischer technischer Begriff:
Missing Runbook
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Runbook fehlt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Runbook fehlt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class RunbookFehltTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class RunbookFehltTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap119: Anti-Pattern: Observability nachträglich angeklebt

Englischer technischer Begriff:
Bolted-on Observability
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Observability nachträglich angeklebt häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Observability nachträglich angeklebt wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class ObservabilityNachtrglichAngeklebtTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class ObservabilityNachtrglichAngeklebtTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}

ap120: Anti-Pattern: Rollback nicht getestet

Englischer technischer Begriff:
Untested Rollback
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Rollback nicht getestet häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Rollback nicht getestet wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
kubectl apply -f deployment.yaml
# Rollback wird erst im Störfall gesucht.
Ziel-Code
# Pattern: Release Runbook - Rollback ist Teil des Deployments.
helm upgrade order-service ./chart --atomic --timeout 5m
helm rollback order-service 18
kubectl rollout status deployment/order-service --timeout=120s

ap121: Anti-Pattern: Lizenzprüfung erst am Release-Tag

Englischer technischer Begriff:
Late License Check
Priorität:
8/10
Art:
Anti-Pattern

Fachliche Situation: In Legacy- und modernen Systemen tritt Lizenzprüfung erst am Release-Tag häufig auf, wenn Zeitdruck, unklare Grenzen oder fehlende Reviews zusammenkommen.

Technische Entscheidung: Das Anti-Pattern wird erkannt und durch eine kleinere, fachlich benannte Struktur ersetzt.

Warum wichtig: Betrieb, Migration und Fehlersuche werden planbar statt zufällig.

Typischer Fehler: Lizenzprüfung erst am Release-Tag wird als pragmatische Abkürzung akzeptiert und später von mehreren Teams kopiert.

Bessere Lösung: Fachliche Verantwortlichkeiten schneiden, Infrastruktur isolieren, Tests ergänzen und die Entscheidung dokumentieren.

Enterprise-Einordnung: Reduziert Wartungskosten, Produktionsrisiken und Kopplung in großen Java-Enterprise-Systemlandschaften.

Ausgangspunkt-Code
public class LizenzprfungErstAmReleaseTagTest {
    @Test void works() {
        assertTrue(service.run(new Order()).isOk());
    }
}
Ziel-Code
// Pattern: Test Pyramid - Fachregel, Integration und Vertrag werden getrennt geprüft.
class LizenzprfungErstAmReleaseTagTest {
    @Test void rejectsOrderWithoutCustomer() {
        assertThrows(ValidationException.class, () -> useCase.place(OrderCommand.withoutCustomer()));
    }
}