Fachlicher Vertrag: unverändert zu erhalten
- Root Cause und Stacktrace bleiben erhalten.
- Fachliche Nicht-gefunden-Fälle sind von technischen Fehlern getrennt.
- Logs enthalten Kontext, aber keine Secrets/PII.
Catch-all, null und System.err wird nachvollziehbar in Domain Exceptions und System.Logger überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.
| Dimension | Legacy | Modern | Migrationskonsequenz |
|---|---|---|---|
| Programmiermodell | imperativ / ohne Framework-Annotationen | explizite Java-Abstraktionen | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 1 direkte Dependencies | 1 direkte Dependencies | 0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen. |
| Öffentliche API | 1 erkannte Methoden | 1 erkannte Methoden | Methoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag. |
| Datenmodell | class LegacyCustomerLookup | class CustomerLookupService, class CustomerNotFoundException | Feldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet. |
| Fehlerverhalten | Legacy-Exceptions und Rückgabewerte | explizitere Fach-/Framework-Fehlerabbildung | Fehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden. |
| Tests | Bestands- und Golden-Master-Tests | Unit-, Slice-, Contract- und Integrationstests | Der Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt. |
| Betrieb | Legacy-Start/Lifecycle | modernes Packaging, Health und externe Konfiguration | Umstellung über kleine Adapter und Golden-Master-Tests statt Big Bang. |
| Rollback | Legacy-Artefakt bleibt unverändert | Modern-Artefakt getrennt deploybar | Kein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein. |
lost root cause and unstable error contracts
cause preservation, log context and negative-path tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyCustomerLookup.java | CustomerLookupService.java + CustomerNotFoundException.java | null/Catch-all wird explizite Fachexception plus Logging. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyCustomerLookup.java | class LegacyCustomerLookup | — | String find(long id) | Exception Shielding (Legacy-Antipattern-Variante) – fängt technische Fehler, verschluckt sie jedoch. | 16 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| CustomerLookupService.java | class CustomerLookupService | — | String find(long id) | Exception Translator | 15 |
| CustomerNotFoundException.java | class CustomerNotFoundException | — | — | — | 7 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| BEIBEHALTEN | org.junit.jupiter:junit-jupiter | BOM/Parent → BOM/Parent | test → test | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.
Migrationsbedeutung: null/Catch-all wird explizite Fachexception plus Logging.
package at.aydin.lab.errors.legacy;
// Design Pattern: Exception Shielding (Legacy-Antipattern-Variante) – fängt technische Fehler, verschluckt sie jedoch.
import java.util.*;
public final class LegacyCustomerLookup {
private final Map<Long, String> data = Map.of(1L, "Aydin");
public String find(long id) {
try {
return data.get(id).toUpperCase();
} catch (Exception ex) {
System.err.println(ex);
return null;
}
}
}
package at.aydin.lab.errors.modern;
import java.util.*;
// Design Pattern: Exception Translator
// Zweck: Technische Abwesenheit wird in eine eindeutige fachliche Exception übersetzt.
public final class CustomerLookupService {
private static final System.Logger LOG = System.getLogger(CustomerLookupService.class.getName());
private final Map<Long, String> data = Map.of(1L, "Aydin");
public String find(long id) {
return Optional.ofNullable(data.get(id)).map(String::toUpperCase).orElseThrow(() -> {
LOG.log(System.Logger.Level.WARNING, "customerId={0} not found", id); return new CustomerNotFoundException(id);
});
}
}
package at.aydin.lab.errors.modern;
public final class CustomerNotFoundException extends RuntimeException {
public CustomerNotFoundException(long id) {
super("Kunde nicht gefunden: " + id);
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 18-EXCEPTION-LOGGING-A01 | Integration/Contract | Kein leerer Catch-Block. | Automatisierter Test und CI-Protokoll |
| 18-EXCEPTION-LOGGING-A02 | Integration/Contract | Root Cause ist über cause zugänglich. | Automatisierter Test und CI-Protokoll |
| 18-EXCEPTION-LOGGING-A03 | Integration/Contract | Nicht gefunden ist reproduzierbar und dokumentiert. | Automatisierter Test und CI-Protokoll |
| 18-EXCEPTION-LOGGING-A04 | Integration/Contract | Sensitive Daten erscheinen nicht im Log. | Automatisierter Test und CI-Protokoll |
| 18-EXCEPTION-LOGGING-A05 | Integration/Contract | Fehlercodes bleiben an API-Grenzen stabil. | Automatisierter Test und CI-Protokoll |
| 18-EXCEPTION-LOGGING-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 18-EXCEPTION-LOGGING-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 18-EXCEPTION-LOGGING-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 18-EXCEPTION-LOGGING-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 18-EXCEPTION-LOGGING-F01 | Fokus | cause preservation, log context and negative-path tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| lost root cause and unstable error contracts | NIEDRIG | cause preservation, log context and negative-path tests | vor Cutover |
Keine zusätzlichen Ressourcen.
Ein Compatibility Adapter kann die neue Exception vorübergehend in das alte null-/Fehlerschema übersetzen, während interne Aufrufer bereits sauber migriert sind.