Modernisierung eines Legacy-Export-Workflows im laufenden Betrieb
Wie ein monolithischer, DLL-basierter Export-Workflow für Kalibrierdaten Schritt für Schritt durch eine ereignisgesteuerte REST-Plattform in C#/.NET ersetzt wurde, während die Auslieferung an Kunden weiterlief.
Kalibrierdaten für E-Motor- und Inverter-Software werden in AVL CRETA verwaltet und für die Softwareintegration und die Auslieferung an Fahrzeughersteller exportiert. Bei Valeo lief dieser Export über einen monolithischen Workflow auf Basis einer DLL-API, deren Abkündigung feststand. Abschalten ging nicht: Kalibrierpakete mussten weiterhin termingerecht bei den Kunden ankommen.
Das Problem
- Eine feste Frist: Die DLL-API würde mit künftigen CRETA-Versionen nicht mehr funktionieren.
- Enge Kopplung: Extraktion, herstellerspezifische Regeln, Dateihandling und Reporting waren verflochten; jede Änderung war riskant.
- Große Artefakte: HEX-, DCM- und PAR-Dateien machten synchrone Verarbeitung langsam.
- Mehrere Kunden, mehrere Varianten: Jeder Hersteller brauchte ein eigenes Exportverhalten.
Der Ansatz
1. Ein generierter statt eines handgeschriebenen Clients. Mit Kiota habe ich aus der OpenAPI-(Swagger-)Beschreibung von CRETA einen typisierten C#-Client generiert. Der neue REST-Client ersetzte die alte DLL vor ihrer Abkündigung, und durch Neugenerierung bleibt er mit der API synchron.
2. Eine Grenze um die Legacy-Welt. Ein Anti-Corruption Layer und Adapter übersetzen zwischen dem externen API-Modell und unserem eigenen Domänenmodell, sodass sich Änderungen nicht von einer Seite auf die andere ausbreiten. Eine Fassade vereinheitlicht Authentifizierung, Session-Tokens und Dateirouting.
3. Ein Modul pro Kundenvariante. Eine Factory instanziiert herstellerspezifische Module zur Laufzeit hinter kleinen, getrennten Schnittstellen. Eine neue Variante bedeutet ein neues Modul, keine Änderung am Kern.
4. Asynchron und ereignisgesteuert. Große Artefakte werden mit nicht blockierender I/O extrahiert und parallel verarbeitet. Die Synchronisation zwischen lokalem Speicher und zentralem NAS ist ereignisgesteuert, mit Wiederholungen und exponentiellem Backoff bei vorübergehenden Fehlern.
5. Schrittweise Einführung mit Tests. Die neue Schicht wurde Schritt für Schritt in die bestehende WPF-Desktopanwendung integriert und durch NUnit-Tests in der CI-Pipeline abgesichert, sodass die Auslieferung nie stillstand.
Das Ergebnis
- Die DLL-Abhängigkeit wurde ersetzt, bevor sie zum Blocker wurde; die Plattform ist bereit für CRETA v6+.
- Kundenspezifisches Verhalten liegt in isolierten Modulen; Änderungen wurden kleiner und sicherer.
- Große Exporte blockieren die Oberfläche nicht mehr, und vorübergehende Netzwerkprobleme werden automatisch behoben.
Was ich gelernt habe
- Generieren, was sich generieren lässt. Ein generierter API-Client beseitigt eine ganze Klasse von Integrationsfehlern.
- Zuerst die Grenze ziehen. Sobald der Anti-Corruption Layer stand, konnte der Rest der Modernisierung dahinter im eigenen Tempo passieren.
- Modernisieren und dabei liefern. Kleine, getestete Schritte in der bestehenden Anwendung brauchten mehr Planung, waren aber weit weniger riskant als eine große Umstellung.