Home
Enterprise Maven MasterclassMaven Masterclass
Echte Projektartefakte

Demo versus Produktion

Konkrete Bewertung vorhandener Artefakte: ausführbar, beispielhaft, simuliert oder noch ohne Produktionsnachweis.

Dokument: Demo versus ProduktionZielgruppe: Entwickler, Architekten und BetriebNiveau: Praxis und ArchitekturStatus: geprüftStand: 10.07.2026

Diese Seite bewertet konkrete Artefakte aus der Masterclass. Sie macht sichtbar, was bereits ausführbar oder konfiguriert ist und was bis zu einer produktiven Enterprise-Lösung zusätzlich nachgewiesen werden müsste.

1. Bewertungsregel

Kennzeichnung Aussage
Vorhanden Datei oder Code existiert im Paket
Lokal ausführbar Der Ablauf kann ohne verteilte Infrastruktur gestartet werden
Beispielkonfiguration Syntax und Struktur sind konkret, Einsatz wurde aber nicht in einer Zielumgebung nachgewiesen
Simuliert Ablauf oder Ergebnis wird im Code modelliert, Fremdsysteme werden nicht wirklich aufgerufen
Produktionsnachweis fehlt Betrieb, Last, Security, Recovery oder Integration sind nicht durch Tests/Umgebung belegt

2. Persistenz: In-Memory ist nicht Datenbank

Master 1 besitzt einen echten Repository-Port und einen echten Adapter:

package com.aydinsude.enterprise.v01.adapter.memory;

import com.aydinsude.enterprise.v01.application.OrderRepository;
import com.aydinsude.enterprise.v01.domain.Order;
import com.aydinsude.enterprise.v01.domain.OrderId;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

// PATTERN: Adapter + Repository implementation - technical storage behind application port.
public final class InMemoryOrderRepository implements OrderRepository {
    private final Map<OrderId, Order> store = new ConcurrentHashMap<>();
    @Override public void save(Order order) { store.put(order.id(), order); }
    @Override public Optional<Order> findById(OrderId id) { return Optional.ofNullable(store.get(id)); }
}

Vorhanden: Speicherung und Lesen innerhalb des laufenden Prozesses.
Nicht vorhanden in diesem Adapter: Neustartfestigkeit, Transaktion, Schema, Migration, Sperrkonzept, Backup und Restore.

Für Produktion wäre mindestens ein persistenter Adapter mit Datenmodell, Migrationen, Transaktionsgrenzen, Integrationstests und Betriebsüberwachung erforderlich.

3. Fachprozess: ausführbar, aber lokal gekoppelt

Master 8 führt den Versicherungsprozess in einer Methode aus:

package com.aydin.enterprise.master8.runnable;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public final class InsuranceProcessFacade {
    public InsuranceResult runDemo(Customer customer) {
        List<String> steps = new ArrayList<>();
        // PATTERN: Pipeline - Quote -> Underwriting -> Policy -> Billing -> Claim -> Payout.
        Quote quote = new QuoteService().createQuote(customer, new BigDecimal("125000.00"));
        steps.add("Quote erstellt: " + quote.quoteNumber());
        UnderwritingDecision decision = new UnderwritingService().decide(quote);
        steps.add("Underwriting: " + decision.status() + " / " + decision.reason());
        if (!decision.accepted()) return InsuranceResult.rejected("Underwriting abgelehnt", steps);
        Policy policy = new PolicyService().issuePolicy(quote, LocalDate.now());
        steps.add("Police erstellt: " + policy.policyNumber());
        Invoice invoice = new BillingService().createInvoice(policy);
        steps.add("Rechnung erstellt: " + invoice.invoiceNumber() + " Betrag=" + invoice.amount());
        PaymentReceipt payment = new PaymentService().settle(invoice);
        steps.add("Zahlung verbucht: " + payment.receiptNumber());
        Claim claim = new ClaimsService().registerClaim(policy, new BigDecimal("8500.00"), "Wasserschaden");
        steps.add("Schaden erfasst: " + claim.claimNumber());
        ClaimDecision claimDecision = new ClaimsService().assess(claim, policy);
        steps.add("Schadenentscheidung: " + claimDecision.status());
        Payout payout = new ClaimsService().payout(claimDecision);
        steps.add("Auszahlung: " + payout.payoutNumber() + " Betrag=" + payout.amount());
        ReinsuranceNote note = new ReinsuranceService().evaluate(policy, claimDecision);
        steps.add("Rueckversicherung: " + note.message());
        AuditTrail audit = new AuditTrail("TRACE-INS-8", steps);
        return InsuranceResult.accepted("Versicherungsablauf abgeschlossen", audit.events());
    }
}

Stärken der Demo: Reihenfolge ist klar, Ablehnung wird behandelt, Zwischenergebnisse werden protokolliert.
Produktionslücken: direkte new-Erzeugung der Services, feste Nummern, keine dauerhafte Zustandsmaschine, keine verteilten Transaktionen, keine Idempotenzschlüssel, keine Wiederaufnahme nach Fehlern und keine echten externen Adapter im gezeigten Flow.

4. Legacy-Modernisierung: Roadmap versus Migration

package com.aydin.enterprise.master14.demo;
import java.util.ArrayList;
import java.util.List;
public final class DemoProcessFacade {
    public DemoResult run() {
        // PATTERN: Pipeline - die fachlichen Schritte laufen kontrolliert nacheinander.
        List<String> steps = new ArrayList<>();
        for (String step : List.of("Legacy Read", "Characterization Test", "Strangler Facade", "Extract Domain", "Outbox Bridge", "Data Migration", "Parallel Run", "Cutover")) {
            steps.add("OK - " + step);
        }
        // PATTERN: Result Object - ein konsistentes Ergebnis fuer Smoke Test und Dokumentation.
        return DemoResult.accepted("Master 14 Legacy Refactoring and Migration System Demo erfolgreich", steps);
    }
}

Die Ausgabe beweist, dass die Reihenfolge als Java-Code ausführbar ist. Sie beweist nicht, dass Legacy-Daten gelesen, fachlich verglichen, migriert oder zurückgerollt wurden. Für Produktion wären konkrete Datenquellen, Mappingregeln, Reconciliation-Ergebnisse, Abbruchkriterien, Cutover-Zustände und Restore-/Rollback-Tests nötig.

5. End-to-End: Orchestrator versus echte Integration

package com.aydin.master25.e2e;

import com.aydin.master25.contracts.CorrelationId;
import com.aydin.master25.contracts.E2eStep;
import java.util.ArrayList;
import java.util.List;

// PATTERN: Facade - offers one simple method for a complex cross-system flow.
public class E2eOrchestrator {
    public List<E2eStep> run(CorrelationId correlationId) {
        List<E2eStep> steps = new ArrayList<>();
        // PATTERN: Pipeline - each step enriches the same end-to-end business story.
        steps.add(new E2eStep("Portal", "create scenario", "scenario accepted " + correlationId.value()));
        steps.add(new E2eStep("Gateway", "route request", "correlation and idempotency checked"));
        steps.add(new E2eStep("Insurance", "issue policy", "policy demo created"));
        steps.add(new E2eStep("Banking", "capture payment", "ledger entry simulated"));
        steps.add(new E2eStep("ERP", "create invoice", "invoice demo created"));
        steps.add(new E2eStep("Logistics", "send document", "document shipment simulated"));
        steps.add(new E2eStep("Legacy", "compare old data", "anti-corruption mapping simulated"));
        steps.add(new E2eStep("Observability", "collect telemetry", "audit trail complete"));
        return steps;
    }
}

Die Wörter simulated und demo created sind bewusst ehrlich. Der Orchestrator erstellt Ergebnisobjekte, aber keine HTTP-, Messaging- oder Datenbankkommunikation. Ein produktiver End-to-End-Nachweis bräuchte laufende Systeme, Verträge, Testdaten, Correlation IDs über Prozessgrenzen, Zeitüberschreitungen, Wiederholungen und eine automatische Ergebnisprüfung.

6. Container und Plattform: konkrete Syntax, Umgebung offen

PostgreSQL-Backup

#!/usr/bin/env bash
set -euo pipefail
: "${PGHOST:=localhost}" "${PGDATABASE:=demo}" "${PGUSER:=demo}"
pg_dump -Fc -h "$PGHOST" -U "$PGUSER" "$PGDATABASE" > "backup-${PGDATABASE}-$(date +%Y%m%d-%H%M%S).dump"

Das Skript ist ausführbar, wenn pg_dump, Netzwerkzugriff und Zugangsdaten vorhanden sind. Für Produktion fehlen typischerweise:

Kubernetes-NetworkPolicy

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-to-db-storage-only
spec:
  podSelector:
    matchLabels:
      tier: app
  policyTypes: [Egress]
  egress:
    - to:
        - podSelector: { matchLabels: { tier: database } }
      ports:
        - protocol: TCP
          port: 5432
    - to:
        - podSelector: { matchLabels: { tier: storage } }
      ports:
        - protocol: TCP
          port: 9000

Die Policy erlaubt App-Pods Egress zu Datenbank und Storage. Vor Produktion müssen unter anderem DNS, Namespace-Grenzen, Default-Deny, Ingress, Monitoring-Zugriffe und die tatsächlichen Labels im Cluster geprüft werden.

7. Testing und Observability: Modulnamen sind noch keine Abdeckung

Master 18 enthält Module wie unit-test-patterns, integration-test-fixtures, contract-test-kit, architecture-test-rules, security-test-kit, migration-test-kit und performance-light-tests. Im aktuellen Paket besitzen diese Module überwiegend kurze README-Beschreibungen; Java-Code liegt dort nicht in derselben Tiefe wie in den frühen Fachmastern. Der vorhandene Java-Einstieg ist vor allem runnable-smoke.

Master 20 besitzt Module wie health-center, metrics-center, log-correlation, trace-flow, audit-timeline, alert-rules, incident-runbook und backup-restore-check. Auch hier bilden die Modulnamen eine vollständige Betriebslandkarte, während der konkrete Java-Code im aktuellen Stand hauptsächlich im Smoke-Modul liegt.

Korrekte Aussage: Die Themen und Modulgrenzen sind dokumentiert und strukturiert.
Zu starke Aussage: Alle Testarten oder Observability-Funktionen seien produktiv implementiert und automatisiert.

8. Produktionsmatrix

Bereich Im Paket sichtbar Für Produktion zusätzlich belegen
Domain Aggregate, Services, Policies, Pattern-Kommentare Grenzfälle, fachliche Tests, Versionierung der Regeln
Application Use Cases und Ports in frühen Mastern Transaktionen, Autorisierung, Idempotenz, Fehlerverträge
Persistenz In-Memory und Plattform-/DB-Themen reale DB-Adapter, Migration, Last, Backup/Restore
Messaging Outbox-/Event-Begriffe und Demo-Schritte Broker, Delivery-Semantik, Retry, DLQ, Schema-Evolution
REST Controller und API-Module AuthN/AuthZ, Validierung, Problem Details, Contract Tests
Security Module und Konfigurationsbeispiele Threat Model, OIDC/RBAC, Secret Rotation, Penetrationstest
Container Docker-/Compose-/K8s-/OpenShift-Dateien Image-Scan, Ressourcenlimits, Probes, Policy, Cluster-Test
Observability Logs/Trace/Audit/Alert-Struktur echte Telemetrie, Dashboards, SLOs, Alarmtests
CI/CD Release- und Pipeline-Themen reproduzierbare Pipeline, Signierung, SBOM, Promotion, Rollback
End-to-End lokaler Master-25-Orchestrator verteilte Umgebung, echte Clients, Testdaten, automatische Assertions

9. Wann darf ein Baustein „produktionsnah“ heißen?

Ein Baustein ist erst dann produktionsnah, wenn nicht nur Code vorhanden ist, sondern auch folgende Nachweise zusammenpassen:

  1. Fachliche Regeln und Fehlerfälle sind getestet.
  2. Externe Schnittstellen besitzen Verträge und Zeitüberschreitungen.
  3. Datenänderungen sind transaktional und wiederholbar.
  4. Konfiguration und Secrets sind umgebungssicher.
  5. Deployment besitzt Ressourcen, Probes und Rollback.
  6. Logs, Metriken und Traces erlauben Ursachenanalyse.
  7. Backup und Restore wurden praktisch getestet.
  8. Security- und Compliance-Anforderungen sind dokumentiert und geprüft.
  9. Ein automatischer End-to-End-Test validiert das Ergebnis statt nur Schritte auszugeben.

10. Empfohlene Reihenfolge für einen echten Ausbau

  1. Einen fachlichen Slice auswählen, zum Beispiel Master 1 Bestellung oder Master 8 Angebot/Police.
  2. Persistenten Adapter ergänzen und mit Testcontainers prüfen.
  3. REST-Vertrag, Validierung und Problem Details absichern.
  4. Outbox oder Messaging mit Idempotenz ergänzen.
  5. Security und Autorisierung an den Use Cases prüfen.
  6. Container- und Plattformkonfiguration in einer echten Laufzeit testen.
  7. Telemetrie, Runbook und Restore-Test hinzufügen.
  8. Erst danach den Slice in den Master-25-End-to-End-Test integrieren.
⌂ Cockpit