SEB4U Java Master System

Java Master Cheat-Sheets - Master Edition

Nicht mehr nur Kurznotizen, sondern eine praxistaugliche Schnellreferenz für Core Java, I/O, Concurrency, Architektur, Spring, Jakarta, Security, Cloud, Algorithmen und Interviews.

21 Themenblöcke
105 Master-Regeln
94 Matrix-Zeilen
42 Code-Snippets
Fundament

A. Arbeitsweise & Package-Standard

Schnell entscheiden, wohin Code gehört, wie Beispiele aufgebaut werden und welche Namen im SEB4U-System gelten.

Master-Regeln

  • Eigene Java-Beispiele verwenden com.seb4u.demo... als Root-Package.
  • Spring-Code liegt unter com.seb4u.demo.spring..., Jakarta-Code unter com.seb4u.demo.jakarta....
  • Domain-Code bleibt frameworkfrei; Spring/Jakarta sind Adapter, nicht Fachlogik.
  • Tiny Snippets dürfen ohne package sein, wenn sie nur Syntax demonstrieren.
  • Ein Cheat-Sheet ist eine Entscheidungs- und Erinnerungsstütze, kein Ersatz für das Handbuch.

Entscheidungsmatrix

OptionWann?Merksatz
Core Java / Algorithmen / I/Ocom.seb4u.demo.<thema>Keine Framework-Abhängigkeit.
Spring Bootcom.seb4u.demo.spring.<thema>Controller, Configuration, Security, Spring Data.
Jakarta EEcom.seb4u.demo.jakarta.<thema>Servlets, JPA, Jakarta Validation ohne Spring.
Testssrc/test/java mit gleichem PackageTestcode spiegelt Produktionspackage.

Copy-Paste Snippets

Package-Matrix java
package com.seb4u.demo.orders;          // Core / Domain / Service ohne Framework
package com.seb4u.demo.io;              // I/O, NIO, Dateien
package com.seb4u.demo.concurrent;      // Virtual Threads, Locks, Queues
package com.seb4u.demo.spring.orders;   // Spring MVC / Spring Boot Adapter
package com.seb4u.demo.jakarta.orders;  // Jakarta Servlet / JPA Adapter
Core Java

B. Java Syntax, Records, Enums & sealed Types

Moderne Java-Sprachelemente schnell richtig einsetzen: Value Objects, Zustände, geschlossene Hierarchien und Pattern Matching.

Master-Regeln

  • Records sind ideal für unveränderliche Daten und Value Objects, nicht für mutable Entities.
  • Invarianten gehören in den compact constructor eines Records.
  • sealed interfaces modellieren geschlossene Domänenzustände oder Ereignistypen.
  • Enums sind gut für stabile, kleine Fachlisten mit Verhalten; nicht für dynamische Datenbank-Listen.
  • Pattern Matching soll Verzweigungen klarer machen, nicht komplexer.

Entscheidungsmatrix

OptionWann?Merksatz
recordValue Object, DTO, Command, EventUnveränderlich, equals/hashCode automatisch.
classEntity mit Identität und kontrollierter ÄnderungBei Lifecycle und Verhalten.
enumKleine feste MengeKann Methoden und Felder enthalten.
sealed interfaceGeschlossene VarianteCompiler kennt alle Implementierungen.

Typische Fallen

  • Record-Felder sind nur flach immutable: eine List muss defensiv kopiert werden.
  • Enum-Namen sind API-Vertrag, wenn sie JSON werden.
  • sealed Types verlieren Wert, wenn überall non-sealed verwendet wird.

Copy-Paste Snippets

Value Object mit Invariante java
package com.seb4u.demo.core;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.Objects;

public record Money(BigDecimal amount, Currency currency) {
    public Money {
        Objects.requireNonNull(amount, "amount");
        Objects.requireNonNull(currency, "currency");
        if (amount.scale() > currency.getDefaultFractionDigits()) {
            throw new IllegalArgumentException("Too many fraction digits for " + currency);
        }
    }

    public Money add(Money other) {
        if (!currency.equals(other.currency)) {
            throw new IllegalArgumentException("Currency mismatch");
        }
        return new Money(amount.add(other.amount), currency);
    }
}
sealed Events mit exhaustiver Verarbeitung java
package com.seb4u.demo.core;

import java.time.Instant;
import java.util.UUID;

public sealed interface OrderEvent permits OrderPlaced, OrderPaid, OrderCancelled {
    UUID orderId();
    Instant occurredAt();
}

public record OrderPlaced(UUID orderId, Instant occurredAt, String customerId) implements OrderEvent {}
public record OrderPaid(UUID orderId, Instant occurredAt, String paymentRef) implements OrderEvent {}
public record OrderCancelled(UUID orderId, Instant occurredAt, String reason) implements OrderEvent {}

final class EventText {
    static String describe(OrderEvent event) {
        return switch (event) {
            case OrderPlaced e -> "Order placed for " + e.customerId();
            case OrderPaid e -> "Payment received: " + e.paymentRef();
            case OrderCancelled e -> "Cancelled: " + e.reason();
        };
    }
}
Core Java

C. Collections, Generics & Typ-Sicherheit

Die passende Datenstruktur wählen, Generics lesbar halten und stabile APIs bauen.

Master-Regeln

  • ArrayList ist der Default für geordnete Listen; LinkedList ist selten schneller.
  • HashMap/HashSet verlangen stabile equals/hashCode-Werte während der Speicherung.
  • Map.computeIfAbsent ist gut für Indizes, aber nicht für teure Nebenwirkungen.
  • Generics sollen fachliche Typfehler verhindern, nicht Signaturen unlesbar machen.
  • Eigene Typed IDs verhindern, dass CustomerId und OrderId vertauscht werden.

Entscheidungsmatrix

OptionWann?Merksatz
ListReihenfolge, DuplikateArrayList als Default.
SetEindeutigkeitHashSet für Lookup, TreeSet für Sortierung.
MapLookup nach SchlüsselHashMap als Default, LinkedHashMap für stabile Reihenfolge.
Queue/DequeArbeitslistenArrayDeque für Stack/Queue ohne Concurrency.

Typische Fallen

  • Mutable Objekte als Map-Key sind gefährlich.
  • Raw Types vermeiden.
  • Wildcard-Signaturen nur dort einsetzen, wo sie echten Nutzen bringen.

Copy-Paste Snippets

Typed ID gegen Parameter-Verwechslung java
package com.seb4u.demo.collections;

import java.util.UUID;

public record OrderId(UUID value) {
    public OrderId {
        if (value == null) throw new IllegalArgumentException("OrderId required");
    }
    public static OrderId newId() { return new OrderId(UUID.randomUUID()); }
}

public record CustomerId(String value) {
    public CustomerId {
        if (value == null || value.isBlank()) throw new IllegalArgumentException("CustomerId required");
    }
}

final class OrderService {
    void assign(OrderId orderId, CustomerId customerId) {
        // assign(customerId, orderId) kompiliert nicht mehr versehentlich.
    }
}
Stabiler Index mit grouping und LinkedHashMap java
package com.seb4u.demo.collections;

import java.util.*;
import java.util.stream.Collectors;

public record Invoice(String customerId, String number, long cents) {}

public final class InvoiceIndex {
    public static Map<String, List<Invoice>> byCustomer(List<Invoice> invoices) {
        return invoices.stream().collect(Collectors.groupingBy(
            Invoice::customerId,
            LinkedHashMap::new,
            Collectors.collectingAndThen(Collectors.toList(), List::copyOf)
        ));
    }
}
Core Java

D. Streams, Optional & funktionale Pipelines

Streams als lesbare Transformationen verwenden und Nebenwirkungen kontrollieren.

Master-Regeln

  • Eine Stream-Pipeline sollte eine klare Frage beantworten: filtern, transformieren, gruppieren, reduzieren.
  • peek ist kein Logging-Konzept; es dient höchstens zum Debuggen.
  • Optional ist Rückgabewert, nicht Feldtyp für Entities und nicht Parameterdefault.
  • parallelStream nur nach Messung und bei CPU-lastigen Operationen verwenden.
  • Eigene Collector lohnen sich, wenn dieselbe Aggregation mehrfach gebraucht wird.

Entscheidungsmatrix

OptionWann?Merksatz
map1:1 TransformationDTOs, Werte extrahieren.
flatMap1:n TransformationListen in Listen flachziehen.
reduceAggregationNur wenn Collector nicht besser passt.
collectStruktur bauenList, Map, Gruppierung, eigene Aggregation.

Typische Fallen

  • Komplexe Stream-Ketten schlechter als klare Schleifen.
  • Stream nach Terminal-Operation nicht wiederverwenden.
  • Nebenwirkungen in map/filter machen Code schwer testbar.

Copy-Paste Snippets

Robuste Aggregation mit record Result java
package com.seb4u.demo.streams;

import java.util.*;
import java.util.stream.Collectors;

public record Sale(String region, String product, long cents) {}
public record RegionRevenue(String region, long totalCents, int count) {}

public final class RevenueReport {
    public static List<RegionRevenue> summarize(List<Sale> sales) {
        return sales.stream()
            .filter(s -> s.cents() > 0)
            .collect(Collectors.groupingBy(Sale::region, Collectors.toList()))
            .entrySet().stream()
            .map(e -> new RegionRevenue(
                e.getKey(),
                e.getValue().stream().mapToLong(Sale::cents).sum(),
                e.getValue().size()))
            .sorted(Comparator.comparingLong(RegionRevenue::totalCents).reversed())
            .toList();
    }
}
Optional an API-Grenze java
package com.seb4u.demo.streams;

import java.util.*;

public record User(String id, String email, boolean active) {}

public final class UserDirectory {
    private final Map<String, User> usersByEmail;

    public UserDirectory(List<User> users) {
        this.usersByEmail = users.stream().collect(
            java.util.stream.Collectors.toUnmodifiableMap(User::email, u -> u));
    }

    public Optional<User> findActiveByEmail(String email) {
        return Optional.ofNullable(usersByEmail.get(email))
            .filter(User::active);
    }
}
Professional Java

E. Exceptions, Validation & Fehlerverträge

Fehler so modellieren, dass Aufrufer korrekt reagieren können und Logs nützlich bleiben.

Master-Regeln

  • Exceptions nicht verschlucken; Kontext ergänzen und Ursache behalten.
  • Fachliche Ablehnung ist oft Result/Validation, nicht zwangsläufig Exception.
  • Technische Fehler an Adaptergrenzen übersetzen, aber nicht verstecken.
  • API-Fehler brauchen stabile Codes, nicht nur freie Texte.
  • try-with-resources für alles, was Closeable/AutoCloseable ist.

Entscheidungsmatrix

OptionWann?Merksatz
Validation ResultEingaben erwartbar ungültigMehrere Fehler sammeln.
Checked ExceptionExterner technischer Fehler, den Aufrufer behandeln sollI/O, Parser, Adapter.
RuntimeExceptionProgrammierfehler, InvariantenbruchFail fast.
Problem DTOHTTP/API FehlervertragStabile machine-readable Codes.

Typische Fallen

  • catch (Exception e) ohne Handlung ist gefährlich.
  • Exception-Texte sind kein maschinenlesbarer Vertrag.
  • Stacktraces nicht an Clients geben.

Copy-Paste Snippets

Result Pattern für fachliche Operationen java
package com.seb4u.demo.errors;

import java.util.List;

public sealed interface Result<T> permits Result.Ok, Result.Invalid, Result.Failed {
    record Ok<T>(T value) implements Result<T> {}
    record Invalid<T>(List<String> violations) implements Result<T> {}
    record Failed<T>(String code, Throwable cause) implements Result<T> {}

    static <T> Result<T> ok(T value) { return new Ok<>(value); }
    static <T> Result<T> invalid(List<String> violations) { return new Invalid<>(List.copyOf(violations)); }
    static <T> Result<T> failed(String code, Throwable cause) { return new Failed<>(code, cause); }
}
Exception mit Kontext und Ursache java
package com.seb4u.demo.errors;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public final class ConfigLoader {
    public String load(Path path) {
        try {
            return Files.readString(path);
        } catch (IOException ex) {
            throw new IllegalStateException("Cannot read config: " + path.toAbsolutePath(), ex);
        }
    }
}
Runtime & I/O

F. I/O, NIO.2, Text & Ressourcen

Dateien sicher, atomar, streaming-basiert und encoding-bewusst verarbeiten.

Master-Regeln

  • Immer Path statt String-Pfade für Dateioperationen verwenden.
  • User-Pfade normalisieren und gegen erlaubten Root prüfen.
  • Große Dateien streamen, nicht komplett in den Heap laden.
  • Atomar schreiben: temporäre Datei im Zielverzeichnis, fsync soweit sinnvoll, dann atomic move.
  • Encoding explizit setzen, meistens UTF-8.

Entscheidungsmatrix

OptionWann?Merksatz
Files.readStringKleine TextdateienNur wenn Größe kontrolliert ist.
Files.linesStreaming TextStream schließen: try-with-resources.
FileChannel.transferToGroße BinärkopienEffizienter als manuelles Buffering.
WatchServiceDateisystemeventsDebounce und Re-Check einplanen.

Typische Fallen

  • Path.normalize allein schützt nicht; startsWith(root) prüfen.
  • Files.lines offen lassen führt zu Ressourcenlecks.
  • Atomic move funktioniert nicht über alle FileStores hinweg.

Copy-Paste Snippets

Sichere Pfadauflösung java
package com.seb4u.demo.io;

import java.nio.file.Path;

public final class SafePathResolver {
    private final Path root;

    public SafePathResolver(Path root) {
        this.root = root.toAbsolutePath().normalize();
    }

    public Path resolveUserPath(String input) {
        Path candidate = root.resolve(input).normalize().toAbsolutePath();
        if (!candidate.startsWith(root)) {
            throw new SecurityException("Path traversal blocked: " + input);
        }
        return candidate;
    }
}
Atomarer Text-Write java
package com.seb4u.demo.io;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

import static java.nio.file.StandardCopyOption.*;

public final class AtomicTextWriter {
    public void write(Path target, String content) throws IOException {
        Path dir = target.toAbsolutePath().getParent();
        Files.createDirectories(dir);
        Path tmp = Files.createTempFile(dir, target.getFileName().toString(), ".tmp");
        try {
            Files.writeString(tmp, content, StandardCharsets.UTF_8,
                StandardOpenOption.TRUNCATE_EXISTING);
            Files.move(tmp, target, ATOMIC_MOVE, REPLACE_EXISTING);
        } finally {
            Files.deleteIfExists(tmp);
        }
    }
}
Große CSV-Datei streaming verarbeiten java
package com.seb4u.demo.io;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.concurrent.atomic.LongAdder;

public final class CsvCounter {
    public long countValidRows(Path csv) throws IOException {
        LongAdder count = new LongAdder();
        try (var lines = Files.lines(csv, StandardCharsets.UTF_8)) {
            lines.skip(1)
                .filter(line -> !line.isBlank())
                .filter(line -> line.split(",", -1).length >= 4)
                .forEach(line -> count.increment());
        }
        return count.sum();
    }
}
Runtime & I/O

G. Datum, Zeit, Locale & Textformatierung

Zeit fachlich korrekt modellieren und typische Zeitzonen- und Locale-Fehler vermeiden.

Master-Regeln

  • Instant für technische Zeitpunkte, LocalDate für fachliche Kalendertage.
  • ZonedDateTime verwenden, wenn Zeitzone Teil der Fachregel ist.
  • Clock injizieren, damit Tests deterministisch sind.
  • Locale niemals implizit aus Default-System ableiten, wenn Ausgabe ein Vertrag ist.
  • Dauer (Duration) und Zeitraum (Period) nicht verwechseln.

Entscheidungsmatrix

OptionWann?Merksatz
InstantAudit, Events, Persistenz-ZeitpunktUTC-basiert.
LocalDateGeburtsdatum, RechnungsdatumOhne Uhrzeit/Zone.
ZonedDateTimeTermine in RegionDST-Regeln relevant.
DurationMillis/Sekunden/StundenTechnische Laufzeit.
PeriodTage/Monate/JahreKalenderlogik.

Typische Fallen

  • LocalDateTime ohne Zone ist kein globaler Zeitpunkt.
  • new Date() in Tests macht Tests flaky.
  • Default Locale kann Produktion anders formatieren als Entwicklung.

Copy-Paste Snippets

Testbare Zeit mit Clock java
package com.seb4u.demo.time;

import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;

public final class TokenExpiry {
    private final Clock clock;

    public TokenExpiry(Clock clock) {
        this.clock = clock;
    }

    public boolean expired(Instant expiresAt) {
        return !Instant.now(clock).isBefore(expiresAt);
    }

    public static TokenExpiry fixedForTest() {
        return new TokenExpiry(Clock.fixed(Instant.parse("2026-01-01T00:00:00Z"), ZoneOffset.UTC));
    }
}
Locale-bewusst formatieren java
package com.seb4u.demo.time;

import java.text.NumberFormat;
import java.util.Currency;
import java.util.Locale;

public final class MoneyFormatter {
    public String format(long cents, Currency currency, Locale locale) {
        NumberFormat format = NumberFormat.getCurrencyInstance(locale);
        format.setCurrency(currency);
        return format.format(cents / 100.0);
    }
}
Runtime & Concurrency

H. Concurrency, Virtual Threads & Synchronisation

Nebenläufigkeit kontrolliert einsetzen: klare Ownership, Timeouts, Bulkheads, Backpressure und Cancellation.

Master-Regeln

  • Mutable Shared State ist der Hauptfeind. Daten lieber unveränderlich weiterreichen.
  • Virtual Threads sind stark für blockierende I/O, nicht automatisch für CPU-bound Workloads.
  • Jede asynchrone Operation braucht Timeout- und Cancellation-Strategie.
  • Semaphore schützt externe Ressourcen als Bulkhead.
  • BlockingQueue modelliert Producer/Consumer mit Backpressure.

Entscheidungsmatrix

OptionWann?Merksatz
Virtual Thread per TaskViele blockierende I/O-AufgabenEinfaches Thread-Modell.
ExecutorService fixed poolCPU-bound ArbeitGröße an CPU orientieren.
SemaphoreExterne Kapazität begrenzenBulkhead.
AtomicReferenceImmutable Snapshot austauschenKonfigurationswechsel.
StampedLock/ReentrantReadWriteLockViel Lesen, wenig SchreibenNur bei gemessener Notwendigkeit.

Typische Fallen

  • synchronized um I/O blockiert unnötig.
  • Unbounded Executor/Queue kann Speicher fressen.
  • ThreadLocal in Virtual-Thread-Massen kritisch prüfen.

Copy-Paste Snippets

Virtual Threads mit Bulkhead java
package com.seb4u.demo.concurrent;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Function;

public final class BulkheadRunner<T, R> implements AutoCloseable {
    private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
    private final Semaphore permits;

    public BulkheadRunner(int maxConcurrent) {
        this.permits = new Semaphore(maxConcurrent);
    }

    public List<R> runAll(List<T> items, Function<T, R> task) throws InterruptedException {
        List<Future<R>> futures = items.stream()
            .map(item -> executor.submit(() -> {
                permits.acquire();
                try { return task.apply(item); }
                finally { permits.release(); }
            }))
            .toList();

        return futures.stream().map(f -> {
            try { return f.get(10, TimeUnit.SECONDS); }
            catch (Exception e) { throw new CompletionException(e); }
        }).toList();
    }

    @Override public void close() { executor.close(); }
}
Producer/Consumer mit Backpressure java
package com.seb4u.demo.concurrent;

import java.util.concurrent.*;

public final class ImportQueue implements AutoCloseable {
    private final BlockingQueue<String> queue = new ArrayBlockingQueue<>(500);
    private final ExecutorService worker = Executors.newSingleThreadExecutor();
    private volatile boolean running = true;

    public void start() {
        worker.submit(() -> {
            while (running || !queue.isEmpty()) {
                String item = queue.poll(250, TimeUnit.MILLISECONDS);
                if (item != null) process(item);
            }
            return null;
        });
    }

    public boolean submit(String item) throws InterruptedException {
        return queue.offer(item, 2, TimeUnit.SECONDS);
    }

    private void process(String item) { /* persistieren, validieren, publizieren */ }

    @Override public void close() {
        running = false;
        worker.close();
    }
}
Runtime & Concurrency

I. CompletableFuture, Async Workflows & Resilience

Asynchrone Ketten lesbar, testbar und begrenzt halten.

Master-Regeln

  • Executor explizit übergeben, statt unbeabsichtigt commonPool zu nutzen.
  • Timeouts gehören in jede externe Kette.
  • exceptionally ist Recovery, handle ist Mapping von Erfolg und Fehler.
  • Nicht wild joinen; an klaren Grenzen warten.
  • Retries brauchen Max-Versuche, Backoff und idempotente Operationen.

Entscheidungsmatrix

OptionWann?Merksatz
thenApplysynchron transformierenKein neuer Async-Schritt.
thenComposeAsync Schritt flachkettenFuture<Future<T>> vermeiden.
allOfParallel sammelnFehlerstrategie bewusst wählen.
orTimeouthartes TimeoutFehler weiterreichen.
completeOnTimeoutFallback-WertDegradation möglich.

Typische Fallen

  • join versteckt checked Exceptions in CompletionException.
  • Async-Ketten ohne Executor sind schwer kontrollierbar.
  • Retry ohne Idempotenz kann doppelte Effekte erzeugen.

Copy-Paste Snippets

Async Orchestrierung mit Timeout und Fallback java
package com.seb4u.demo.async;

import java.time.Duration;
import java.util.concurrent.*;

public final class PricingGateway {
    private final Executor executor;

    public PricingGateway(Executor executor) {
        this.executor = executor;
    }

    public CompletableFuture<Long> priceCents(String sku) {
        return CompletableFuture.supplyAsync(() -> callRemotePricing(sku), executor)
            .orTimeout(800, TimeUnit.MILLISECONDS)
            .exceptionally(ex -> fallbackPrice(sku));
    }

    private long callRemotePricing(String sku) { return 1299L; }
    private long fallbackPrice(String sku) { return 999L; }
}
Alle Ergebnisse sammeln ohne alles zu verlieren java
package com.seb4u.demo.async;

import java.util.List;
import java.util.concurrent.*;
import java.util.function.Supplier;

public record Try<T>(T value, Throwable error) {
    static <T> Try<T> ok(T value) { return new Try<>(value, null); }
    static <T> Try<T> failed(Throwable error) { return new Try<>(null, error); }
}

public final class BatchAsync {
    public static <T> List<Try<T>> run(List<Supplier<T>> tasks, Executor executor) {
        var futures = tasks.stream()
            .map(task -> CompletableFuture.supplyAsync(task, executor)
                .<Try<T>>thenApply(Try::ok)
                .exceptionally(Try::failed))
            .toList();
        return futures.stream().map(CompletableFuture::join).toList();
    }
}
Build & Architektur

J. Maven, Module & Projektstruktur

Reproduzierbare Builds, klare Modulgrenzen und saubere Dependency-Richtung sichern.

Master-Regeln

  • Domain-Module dürfen Spring/Jakarta nicht kennen.
  • Parent-POM bündelt Versionen und Plugin-Konfiguration.
  • Dependency Management zentralisieren, Dependencies pro Modul explizit halten.
  • Tests spiegeln Package-Struktur.
  • Build-Befehle dokumentieren: compile, test, package, verify.

Entscheidungsmatrix

OptionWann?Merksatz
Parent POMVersionen/Plugins zentralKeine Fachlogik.
Domain ModulFachmodellKeine Frameworks.
Application ModulUse Cases und PortsHängt von Domain ab.
Adapter ModulI/O, HTTP, DB, MessagingHängt von Application ab.

Schnellcheck / Befehle

mvn -q testmvn -q -pl commerceflow-domain testmvn -q -DskipTests packagemvn -q verify

Copy-Paste Snippets

Maven-Modulrichtung xml
<modules>
  <module>commerceflow-domain</module>
  <module>commerceflow-application</module>
  <module>commerceflow-adapter-file</module>
  <module>commerceflow-adapter-spring</module>
  <module>commerceflow-tests</module>
</modules>
Compiler Release zentral setzen xml
<properties>
  <maven.compiler.release>25</maven.compiler.release>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <release>${maven.compiler.release}</release>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>
Testing

K. Testing, Testbarkeit & Qualität

Tests so schreiben, dass sie Verhalten schützen, schnell Feedback geben und Refactoring ermöglichen.

Master-Regeln

  • Unit Tests testen Fachlogik ohne Infrastruktur.
  • Integration Tests testen Adapter, Datenbank, HTTP oder Messaging.
  • Tests brauchen klare Arrange-Act-Assert-Struktur.
  • Clock, IDs und externe Ports injizieren, statt statisch zu erzeugen.
  • Testdaten-Builder reduzieren Rauschen, dürfen aber Invarianten nicht umgehen.

Entscheidungsmatrix

OptionWann?Merksatz
Unit TestDomain und Use CasesSchnell, ohne Container.
Integration TestDB/HTTP/Messaging AdapterLangsamer, aber realitätsnah.
Contract TestAPI-VertragConsumer/Provider absichern.
ArchitekturtestDependency-RegelnRegeln automatisieren.

Typische Fallen

  • Mocke nicht Value Objects.
  • Tests, die Implementierungsdetails prüfen, brechen bei gutem Refactoring.
  • Thread.sleep in Tests ist fast immer ein Geruch.

Copy-Paste Snippets

Deterministischer Unit Test java
package com.seb4u.demo.testing;

import org.junit.jupiter.api.Test;
import java.time.*;
import static org.junit.jupiter.api.Assertions.*;

final class TokenExpiryTest {
    @Test
    void token_is_expired_after_expiry_instant() {
        Clock clock = Clock.fixed(Instant.parse("2026-01-01T10:00:00Z"), ZoneOffset.UTC);
        TokenExpiry expiry = new TokenExpiry(clock);

        assertTrue(expiry.expired(Instant.parse("2026-01-01T09:59:59Z")));
        assertFalse(expiry.expired(Instant.parse("2026-01-01T10:00:01Z")));
    }
}
Testdaten-Builder java
package com.seb4u.demo.testing;

import java.util.UUID;

public final class OrderBuilder {
    private UUID id = UUID.randomUUID();
    private String customerId = "C-100";

    public OrderBuilder customer(String customerId) {
        this.customerId = customerId;
        return this;
    }

    public TestOrder build() {
        return new TestOrder(id, customerId);
    }
}

record TestOrder(UUID id, String customerId) {}
Professional Backend

L. Hexagonale Architektur, DDD & CommerceFlow

Fachlogik von Frameworks trennen und Use Cases über Ports testbar halten.

Master-Regeln

  • Domain modelliert Sprache und Regeln des Fachbereichs.
  • Application Layer orchestriert Use Cases und spricht Ports an.
  • Adapter implementieren Ports für Datei, Datenbank, HTTP, Messaging.
  • Controller/Servlets sollen nicht direkt Fachregeln enthalten.
  • Events beschreiben Vergangenes, Commands beschreiben Absicht.

Entscheidungsmatrix

OptionWann?Merksatz
EntityIdentität und LifecycleOrder, Customer.
Value ObjectWertgleichheit und InvarianteMoney, Email, Address.
CommandAbsicht aus AußenweltPlaceOrderCommand.
EventFakt, der passiert istOrderPlaced.
PortAbhängigkeit nach außenOrderRepository, EventPublisher.

Typische Fallen

  • JPA Entity ist nicht automatisch Domain Model.
  • DTOs nicht quer durch alle Schichten ziehen.
  • Ports nicht mit Framework-Typen verschmutzen.

Copy-Paste Snippets

Use Case mit Ports java
package com.seb4u.demo.commerce.application;

import com.seb4u.demo.commerce.domain.*;

public final class PlaceOrderUseCase {
    private final OrderRepository orders;
    private final EventPublisher events;

    public PlaceOrderUseCase(OrderRepository orders, EventPublisher events) {
        this.orders = orders;
        this.events = events;
    }

    public OrderId handle(PlaceOrderCommand command) {
        Order order = Order.place(command.customerId(), command.items());
        orders.save(order);
        events.publish(order.pullEvents());
        return order.id();
    }
}
Port Interfaces java
package com.seb4u.demo.commerce.application;

import com.seb4u.demo.commerce.domain.*;
import java.util.List;
import java.util.Optional;

public interface OrderRepository {
    void save(Order order);
    Optional<Order> findById(OrderId id);
}

public interface EventPublisher {
    void publish(List<OrderEvent> events);
}
Enterprise Java

M. Spring Boot, REST & Web Layer

Spring Boot als Adapter sauber einsetzen: schlanke Controller, DTOs, Validation, Fehlervertrag.

Master-Regeln

  • Controller übersetzen HTTP in Use-Case-Aufrufe, enthalten aber keine Fachlogik.
  • DTOs sind API-Verträge und dürfen sich von Domain Objects unterscheiden.
  • Validation an Eingangsgrenzen, Invarianten zusätzlich im Domain Model.
  • ProblemDetail oder ein eigenes Problem DTO für Fehlerantworten verwenden.
  • Configuration Properties statt verstreuter @Value Strings.

Entscheidungsmatrix

OptionWann?Merksatz
@RestControllerHTTP AdapterNur Request/Response Mapping.
@ServiceApplication ServiceUse-Case-Orchestrierung.
@RepositoryPersistence AdapterDB-Ausnahmen übersetzen.
@ConfigurationPropertiesKonfigurationTypisiert und testbar.

Typische Fallen

  • Entities direkt als JSON ausgeben.
  • Businesslogik in Controller packen.
  • Globale Exception Handler ohne stabile Fehlercodes.

Copy-Paste Snippets

Schlanker REST Controller java
package com.seb4u.demo.spring.orders;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    private final PlaceOrderService service;

    public OrderController(PlaceOrderService service) {
        this.service = service;
    }

    @PostMapping
    ResponseEntity<OrderResponse> place(@Valid @RequestBody PlaceOrderRequest request) {
        String id = service.place(request.customerId());
        return ResponseEntity.accepted().body(new OrderResponse(id));
    }

    public record PlaceOrderRequest(@NotBlank String customerId) {}
    public record OrderResponse(String orderId) {}
}
ProblemDetail Handler java
package com.seb4u.demo.spring.errors;

import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestControllerAdvice
public class ApiExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    ProblemDetail badRequest(IllegalArgumentException ex) {
        ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
        problem.setTitle("Invalid request");
        problem.setDetail(ex.getMessage());
        problem.setProperty("code", "REQUEST_INVALID");
        return problem;
    }
}
Enterprise Java

N. Jakarta EE, Servlet & Persistence Adapter

Jakarta als Web-/Persistence-Adapter verwenden, ohne Domain an Container-APIs zu koppeln.

Master-Regeln

  • Servlets sind Adapter und sollten Use Cases aufrufen.
  • JPA Entities sind Persistence-Modell; Domain kann getrennt bleiben.
  • Transaktionen gehören an Use-Case-/Repository-Grenzen.
  • Bean Validation prüft Eingaben, nicht alle Fachregeln.
  • Jakarta-Packages bleiben com.seb4u.demo.jakarta....

Entscheidungsmatrix

OptionWann?Merksatz
ServletHTTP ohne SpringMapping und Statuscodes.
JPA EntityDB MappingNicht automatisch API DTO.
CDI BeanDependency InjectionContainerverwaltete Services.
Bean ValidationEingabeformateNotBlank, Email, Size etc.

Typische Fallen

  • EntityManager im Domain Model verwenden.
  • Lazy Loading im JSON Serializer auslösen.
  • Servlet mit SQL und Fachlogik überladen.

Copy-Paste Snippets

Jakarta Servlet als Adapter java
package com.seb4u.demo.jakarta.orders;

import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;

@WebServlet("/orders")
public class OrderServlet extends HttpServlet {
    private final PlaceOrderUseCase useCase = new PlaceOrderUseCase();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String customerId = req.getParameter("customerId");
        String orderId = useCase.place(customerId);
        resp.setStatus(HttpServletResponse.SC_ACCEPTED);
        resp.setContentType("application/json");
        resp.getWriter().write("{"orderId":"" + orderId + ""}");
    }
}
JPA Entity getrennt vom Domain Object java
package com.seb4u.demo.jakarta.persistence;

import jakarta.persistence.*;

@Entity
@Table(name = "orders")
public class OrderEntity {
    @Id
    private String id;
    private String customerId;
    private String status;

    protected OrderEntity() {}

    public OrderEntity(String id, String customerId, String status) {
        this.id = id;
        this.customerId = customerId;
        this.status = status;
    }
}
Enterprise Java

O. JDBC, Transaktionen & Persistence Patterns

Datenbankzugriffe klar kapseln, Transaktionen bewusst begrenzen und Persistenzfehler übersetzen.

Master-Regeln

  • Connection-Lifecycle immer über try-with-resources oder Pooling steuern.
  • PreparedStatement statt String-Konkatenation.
  • Transaktionen sollten fachliche Konsistenzgrenzen abbilden.
  • Outbox Pattern verhindert Eventverlust zwischen DB und Messaging.
  • N+1-Probleme und Lazy Loading aktiv im Blick behalten.

Entscheidungsmatrix

OptionWann?Merksatz
JDBCVolle Kontrolle, einfache QueriesMehr Code, weniger Magie.
JPAObjektmapping und Unit of WorkLazy/N+1 beachten.
Flyway/LiquibaseSchema-MigrationVersioniert und reproduzierbar.
OutboxDB + Event PublishEventual Consistency.

Typische Fallen

  • Autocommit unbewusst nutzen.
  • SQL-Injection durch String-Verkettung.
  • Transaktion über Netzwerkcalls offen halten.

Copy-Paste Snippets

JDBC Repository mit Transaktion java
package com.seb4u.demo.persistence;

import javax.sql.DataSource;
import java.sql.*;

public final class JdbcOrderRepository {
    private final DataSource dataSource;

    public JdbcOrderRepository(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void insert(String id, String customerId) throws SQLException {
        String sql = "insert into orders(id, customer_id, status) values (?, ?, ?)";
        try (Connection con = dataSource.getConnection()) {
            boolean oldAutoCommit = con.getAutoCommit();
            con.setAutoCommit(false);
            try (PreparedStatement ps = con.prepareStatement(sql)) {
                ps.setString(1, id);
                ps.setString(2, customerId);
                ps.setString(3, "PLACED");
                ps.executeUpdate();
                con.commit();
            } catch (SQLException ex) {
                con.rollback();
                throw ex;
            } finally {
                con.setAutoCommit(oldAutoCommit);
            }
        }
    }
}
Outbox Insert in gleicher Transaktion java
package com.seb4u.demo.persistence;

import java.sql.*;
import java.time.Instant;

public final class OutboxWriter {
    public void append(Connection con, String aggregateId, String type, String payload) throws SQLException {
        try (PreparedStatement ps = con.prepareStatement("""
            insert into outbox(id, aggregate_id, event_type, payload, created_at)
            values (?, ?, ?, ?, ?)
            """)) {
            ps.setString(1, java.util.UUID.randomUUID().toString());
            ps.setString(2, aggregateId);
            ps.setString(3, type);
            ps.setString(4, payload);
            ps.setTimestamp(5, Timestamp.from(Instant.now()));
            ps.executeUpdate();
        }
    }
}
Enterprise Java

P. Security, Auth & sichere APIs

Sicherheitsentscheidungen als feste Regeln verankern: Validierung, Auth, Geheimnisse, Hashing, Fehlerantworten.

Master-Regeln

  • Passwörter nie selbst verschlüsseln; starke Passwort-Hashing-Verfahren nutzen.
  • Secrets gehören nicht ins Git-Repository.
  • Input Validation und Output Encoding sind getrennte Aufgaben.
  • Authorization immer serverseitig prüfen, nicht nur im Frontend.
  • Fehlerantworten dürfen keine internen Details preisgeben.

Entscheidungsmatrix

OptionWann?Merksatz
AuthenticationWer bist du?Login, Token, Session.
AuthorizationWas darfst du?Rollen/Rechte/Policies.
ValidationIst Input formal gültig?Grenzen prüfen.
Sanitization/EncodingSichere AusgabeKontextabhängig: HTML, SQL, JSON.
Rate LimitMissbrauch begrenzenAPI-Gateway oder App-Schicht.

Typische Fallen

  • JWT ohne Ablaufzeit.
  • Rollen im Client vertrauen.
  • Stacktrace an HTTP-Client ausgeben.
  • Passwörter loggen.

Copy-Paste Snippets

HMAC Signatur prüfen java
package com.seb4u.demo.security;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HexFormat;

public final class HmacVerifier {
    public boolean valid(String body, String expectedHex, byte[] secret) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret, "HmacSHA256"));
        byte[] actual = mac.doFinal(body.getBytes(StandardCharsets.UTF_8));
        byte[] expected = HexFormat.of().parseHex(expectedHex);
        return MessageDigest.isEqual(actual, expected);
    }
}
Spring Security Method Guard java
package com.seb4u.demo.spring.security;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class AdminOrderService {
    @PreAuthorize("hasAuthority('ORDER_CANCEL')")
    public void cancelOrder(String orderId, String reason) {
        // Use Case aufrufen, Audit Event schreiben
    }
}
Production

Q. Logging, Metrics, Performance & JVM

Produktionsreife durch messbare, strukturierte und ressourcenschonende Anwendungen erreichen.

Master-Regeln

  • Logs sollen strukturierte Felder enthalten: correlationId, orderId, userId, status.
  • Metriken brauchen Zähler, Timer, Gauges und sinnvolle Labels.
  • Performance erst messen, dann optimieren.
  • Memory Leaks entstehen oft durch statische Collections, Caches ohne Limits und Listener ohne Deregistrierung.
  • GC-Tuning ist später Schritt; zuerst Allocation Rate, Datenstrukturen und I/O prüfen.

Entscheidungsmatrix

OptionWann?Merksatz
CounterEreignisse zählenrequests_total, orders_created.
TimerDauer messenHTTP, DB, externe Calls.
GaugeMomentwertQueue length, active workers.
Structured LogDebug und AuditKeine Secrets loggen.
ProfilerHotspots findenNicht raten.

Typische Fallen

  • Hohe Kardinalität bei Metric Labels.
  • Sensible Daten in Logs.
  • Mikrobenchmarks ohne Warmup.

Copy-Paste Snippets

Strukturierter Log-Wrapper java
package com.seb4u.demo.observability;

import java.time.Instant;
import java.util.Map;

public final class StructuredLog {
    public static void info(String event, Map<String, ?> fields) {
        System.out.println(Map.of(
            "level", "INFO",
            "event", event,
            "time", Instant.now().toString(),
            "fields", fields
        ));
    }
}
Einfache StopWatch für Hotspot-Suche java
package com.seb4u.demo.performance;

public final class TimerProbe implements AutoCloseable {
    private final String name;
    private final long start = System.nanoTime();

    public TimerProbe(String name) { this.name = name; }

    @Override public void close() {
        long millis = (System.nanoTime() - start) / 1_000_000;
        System.out.println(name + " took " + millis + " ms");
    }
}
Fullstack

R. Fullstack Java, HTTP, JSON & UI-Flows

Backend-APIs und einfache UIs konsistent verbinden: Validierung, Fehler, Pagination, Uploads und Exporte.

Master-Regeln

  • HTTP-Statuscode, Fehlercode und Fehlermeldung müssen zusammenpassen.
  • Pagination nie ohne maximale Page Size anbieten.
  • Filter/Sortierung als stabilen Vertrag dokumentieren.
  • Datei-Uploads brauchen Größenlimit, Content-Type-Prüfung und sichere Pfade.
  • Frontend validiert für UX, Backend validiert für Sicherheit.

Entscheidungsmatrix

OptionWann?Merksatz
GETLesen ohne SeiteneffektCachebar, idempotent.
POSTErzeugen/AktionNicht idempotent oder mit Idempotency-Key.
PUTErsetzenIdempotent.
PATCHTeiländerungSemantik sauber dokumentieren.
DELETELöschen/StornierenOft fachlich als Cancel modellieren.

Typische Fallen

  • Unbegrenzte Exporte synchron ausführen.
  • Dateinamen aus Upload direkt verwenden.
  • HTTP 200 für Fachfehler ohne Fehlervertrag.

Copy-Paste Snippets

Pagination Response Contract java
package com.seb4u.demo.spring.web;

import java.util.List;

public record PageResponse<T>(
    List<T> items,
    int page,
    int size,
    long totalItems,
    int totalPages
) {
    public PageResponse {
        items = List.copyOf(items);
        if (size <= 0 || size > 100) throw new IllegalArgumentException("Invalid page size");
    }
}
Idempotency-Key Grundidee java
package com.seb4u.demo.spring.web;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/payments")
public class PaymentController {
    @PostMapping
    String pay(@RequestHeader("Idempotency-Key") String idempotencyKey,
               @RequestBody PaymentRequest request) {
        return "accepted:" + idempotencyKey;
    }

    record PaymentRequest(String orderId, long amountCents) {}
}
Cloud & Distributed Systems

S. Microservices, Messaging & Cloud

Verteilte Systeme bewusst entwerfen: Idempotenz, Konsistenz, Messaging, Retries und Observability.

Master-Regeln

  • Microservices sind organisatorische und technische Grenzen, nicht nur kleine REST-Apps.
  • Netzwerk ist unzuverlässig: Timeouts, Retries, Circuit Breaker und Idempotenz einplanen.
  • Events sind Verträge; Versionierung und Kompatibilität sind Pflicht.
  • Verteilte Transaktionen vermeiden; Saga/Outbox/Inbox einsetzen.
  • Jeder Request braucht Correlation ID über Servicegrenzen hinweg.

Entscheidungsmatrix

OptionWann?Merksatz
RESTSynchrone Abfrage/CommandDirektes Feedback, gekoppelte Verfügbarkeit.
MessagingAsynchrone EreignisseEntkopplung, Eventual Consistency.
OutboxDB und Event sicher koppelnProducer-Seite.
InboxDeduplizierung eingehender EventsConsumer-Seite.
SagaLanglaufender WorkflowKompensationen statt 2PC.

Typische Fallen

  • Retry Storm ohne Backoff.
  • Events mit internen DB-Strukturen publizieren.
  • Keine Idempotency Keys bei Zahlungs-/Bestelloperationen.

Copy-Paste Snippets

Idempotenter Consumer java
package com.seb4u.demo.cloud;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public final class IdempotentConsumer {
    private final Set<String> processed = ConcurrentHashMap.newKeySet();

    public void handle(String eventId, Runnable action) {
        if (!processed.add(eventId)) {
            return; // bereits verarbeitet
        }
        action.run();
    }
}
Docker Compose Service Skeleton yaml
services:
  commerceflow-api:
    build:
      context: .
      dockerfile: Dockerfile.spring
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: docker
      DB_HOST: postgres
    depends_on:
      - postgres

  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: commerceflow
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
Algorithms

T. Algorithmen & Datenstrukturen in Java

Interview- und Praxisalgorithmen schnell erkennen, korrekt implementieren und Big-O sauber begründen.

Master-Regeln

  • Erst Problemklasse erkennen: Lookup, Sortierung, Graph, Fenster, DP, Backtracking.
  • Big-O immer für Zeit und Speicher angeben.
  • HashMap ist häufig der Schritt von O(n²) zu O(n).
  • PriorityQueue für Top-K und Scheduling verwenden.
  • Bei Graphen visited-Set und Zyklusfälle früh klären.

Entscheidungsmatrix

OptionWann?Merksatz
Two PointersSortiertes Array/Palindrome/PaareO(n), wenig Speicher.
Sliding WindowSubarray mit FensterbedingungO(n).
BFSKürzeste Wege in ungewichteten GraphenQueue.
DFSKomponenten, Topologie, BacktrackingStack/Rekursion.
DijkstraNichtnegative gewichtete KantenPriorityQueue.
Union-FindDynamische KomponentenFast O(1) amortisiert.

Typische Fallen

  • Rekursion ohne Abbruchbedingung.
  • Integer Overflow bei Comparator a-b.
  • Visited zu spät setzen kann Queue aufblasen.

Copy-Paste Snippets

Sliding Window java
package com.seb4u.demo.algorithms;

public final class LongestOnesAfterFlip {
    public int longest(int[] bits, int maxZeros) {
        int left = 0, zeros = 0, best = 0;
        for (int right = 0; right < bits.length; right++) {
            if (bits[right] == 0) zeros++;
            while (zeros > maxZeros) {
                if (bits[left++] == 0) zeros--;
            }
            best = Math.max(best, right - left + 1);
        }
        return best;
    }
}
Dijkstra Skeleton java
package com.seb4u.demo.algorithms;

import java.util.*;

public final class Dijkstra {
    record Edge(String to, int weight) {}
    record Node(String id, int distance) {}

    public Map<String, Integer> shortest(Map<String, List<Edge>> graph, String start) {
        Map<String, Integer> dist = new HashMap<>();
        PriorityQueue<Node> pq = new PriorityQueue<>(Comparator.comparingInt(Node::distance));
        dist.put(start, 0);
        pq.add(new Node(start, 0));
        while (!pq.isEmpty()) {
            Node current = pq.poll();
            if (current.distance() != dist.get(current.id())) continue;
            for (Edge edge : graph.getOrDefault(current.id(), List.of())) {
                int next = current.distance() + edge.weight();
                if (next < dist.getOrDefault(edge.to(), Integer.MAX_VALUE)) {
                    dist.put(edge.to(), next);
                    pq.add(new Node(edge.to(), next));
                }
            }
        }
        return dist;
    }
}
Job Ready

U. Code Review, Interview & Produktions-Checklisten

Schnell erkennen, ob Code produktionsreif, wartbar und interviewfest ist.

Master-Regeln

  • Jede öffentliche API braucht klare Namen, Grenzen und Fehlerverhalten.
  • Jede externe Abhängigkeit braucht Timeout, Retry-Entscheidung und Logging-Kontext.
  • Jede Collection-Wahl soll begründbar sein.
  • Jede Nebenläufigkeit braucht Ownership-Regel und Shutdown-Pfad.
  • Jede Security-relevante Operation braucht Negativtests.

Entscheidungsmatrix

OptionWann?Merksatz
Code Review CoreLesbarkeit, Invarianten, DatenstrukturenKleine Methoden, gute Namen.
Code Review RuntimeI/O, Threads, RessourcenLeaks, Timeouts, Shutdown.
Code Review APIDTOs, Statuscodes, FehlerStabile Verträge.
Code Review ProductionLogs, Metrics, ConfigBetreibbarkeit.

Schnellcheck / Befehle

Kann ich den Fehler reproduzieren?Ist der Fehlervertrag stabil?Gibt es einen Test für die wichtigste Fachregel?Was passiert bei Timeout?Was passiert bei leerem Input?Was passiert bei 10x Last?

Copy-Paste Snippets

Review-Check als Kommentarvorlage text
Code Review Checklist
- [ ] Package Standard: com.seb4u.demo..., spring oder jakarta korrekt?
- [ ] Fachlogik frei von Frameworks?
- [ ] I/O: try-with-resources, sichere Paths, explizites Encoding?
- [ ] Concurrency: Timeout, Cancellation, Shutdown, Backpressure?
- [ ] API: DTOs, Validation, Fehlercodes, keine Stacktraces?
- [ ] Tests: wichtigste Fachregel + Fehlerfall + Grenze?
- [ ] Observability: Korrelation, strukturierte Logs, keine Secrets?
Senior-Antwortstruktur im Interview text
1. Problemgrenze klären: Input, Output, Constraints, Fehlerfälle.
2. Einfachste korrekte Lösung erklären.
3. Datenstruktur begründen und Big-O nennen.
4. Edge Cases nennen: null/leer/groß/duplikate/concurrency.
5. Testfälle skizzieren.
6. Produktionsaspekte ergänzen: Logging, Timeout, Security, Monitoring.