Modernisierung von Software: Inkrementelles Re-Engineering für eine nachhaltige Software-Entwicklung

von Michael Hava MSc, DI (FH) Josef Jank MSc, und DI (FH) Alexander Leutgeb

© iStock/ Christian Horz
© iStock/ Christian Horz

05.05.2021

Bei langlebigen Software-Systemen übersteigen die Wartungskosten die initialen Entwicklungskosten bei weitem. Entkommen Sie der Kostenfalle durch rechtzeitige pro-aktive Modernisierungsmaßnahmen. Ein evolutionäres Vorgehen garantiert planbare Kosten, kontinuierliche Releases und unmittelbaren Kundennutzen bei überschaubarem Risiko.

Raus aus den (technischen) Schulden

Untersuchungen zeigen, dass der Erfolg von Firmen zunehmend von Software bestimmt wird. Einer der erfolgreichster Händler (Amazon) ist daher nicht zufällig eine der erfolgreichsten Softwarefirmen, sondern hat damit die Grundlage für den Erfolg geschaffen. Insbesondere im industriellen Umfeld entstand im Zuge der Digitalisierung im Laufe der letzten Jahrzehnte zunehmender Bedarf im Bereich der Softwareentwicklung, Viele Firmen haben daher eigene Software-Entwicklungsteams etabliert. Diese bestanden anfangs allerdings oftmals aus reinen Fachdomänenexperten ohne tiefergreifende Software-Entwicklungsexpertise. Da sich Software-Entwicklung immer mehr als Kernthema herauskristallisierte, wurde die Notwendigkeit der Software-Entwicklung als eigenständiges Disziplin erkannt und die Teams um Software Ingenieure erweitert. Die lange Entwicklungshistorie, die heterogenen Teams und eine entsprechende Entwickler-Fluktuation führen zu einer Heterogenität hinsichtlich der Entwicklungsmethodik, der verwendeten Technologien und der Code-Qualität. Steuert man dieser Heterogenität nicht durch fortwährende Konsolidierung entgegen, steigen die Kosten für die Wartung der Software über die Jahre enorm an. Darüber hinaus sind Änderungen immer schwieriger und die Integration neuer Funktionalität ist nur mehr mit hohem Aufwand und Risiko möglich. Im schlimmsten Fall können so die technischen Schulden in einem “technischen Bankrott” führen (siehe Abbildung 1).

Durch eine gezielte Modernisierung kann man Kosten und Risiko für die Wartung stark reduzieren und auf zukünftige Anforderungen schneller reagieren. Durch eine inkrementelle Vorgehensweise können die Anpassungen kontinuierlich in den Produktivbetrieb übernommen werden und es wird sichergestellt, dass das System stets den Anforderungen genügt. Dabei lässt sich der Aufwand für die Modernisierung im Verhältnis zu einer Neuentwicklung relativ leicht und genau abschätzen. Ein weiterer Aspekt technischer Anwendungen ist oftmals, dass die Anforderungen hinsichtlich Modellgrößen über die Jahre stark gewachsen sind, sodass die Laufzeiten für Berechnungen und der Speicherbedarf mit der aktuellen Umsetzung der Software nicht mehr praktikabel sind. Im Zuge einer Modernisierung können solche Engpässe identifiziert und durch eine adäquate Software Umsetzung unter Ausnutzung des Paralleliserungspotentials moderner Hardware-Architekturen behoben werden.
 

Die ideale Vorgehensweise ist abhängig von der Problemstellung

Die Grundlage für eine technisch und wirtschaftlich erfolgreiche Modernisierung von Legacy-Software ist eine gut überlegte Gesamtstrategie. Dabei ist es wichtig möglichst unvoreingenommen an das Thema heranzugehen und neben der Modernisierung und Sanierung auch radikale Ansätze wie eine vollständige Neuentwicklung oder den Einsatz von Standardsoftware zu berücksichtigen und zu bewerten. Bei der Frage, ob man existierende Software einem Reengineering unterzieht, oder stattdessen eine Neuentwicklung projektiert, ist die erstgenannte Alternative häufig vorzuziehen, weil das Reverse-Engineering bis hin zu den Requirements enorm aufwändig sein kann (siehe Abbildung 2). Oftmals ist fast keine Dokumentation verfügbar und das Know-hHow nur mehr im Quellcode manifestiert. Aufgrund der substantiell geringeren Kosten, Risiken und Durchlaufzeit wird man sich daher in vielen Fällen für eine spezifische Modernisierung entscheiden, wo die notwendigen Re-Engineering Maßnahmen (Re-Code, Re-Design, Re-Specify, Re-Think) gezielt für die unterschiedlichen Teile des Systems identifiziert werden. Bei der Wahl der jeweiligen Maßnahme ist abzuwägen, ob der daraus resultierende Nutzen den Aufwand rechtfertigt.

Bei der Modernisierung sollten Teile mit hohem und niedrigem Änderungsbedarf identifiziert und strategisch unterschiedlich behandelt werden. Bei den stabilen Teilen mit geringem Änderungsbedarf sollte man immer kritisch hinterfragen, ob Aufwand und Risiko den potenziell geringen Nutzen rechtfertigen. Anti-Corruption Layer bieten die Möglichkeit einer schrittweisen Migration vom legacy zum neuen System, wobei zu jedem Zeitpunkt ein stabiles Produktivsystem zur Verfügung steht und die weitere Modernisierung nach Bedarf entschieden werden kann (siehe Abbildung 3). Ein Anti-Corruption Layer isoliert Teile von einem Gesamtsystem und stellt die Kompatibilität zwischen unterschiedlich evolutionär entwickelten Teilen sicher (Legacy Anwendung mit neuen Code-Teilen, neue Anwendung mit Legacy Code-Teilen).

Eine wichtige Strategie im Zuge einer Modernisierung ist kontinuierliche Reduktion von Abhängigkeiten und die Verbesserung durch Modularisierung. Das Ziel sind lose gekoppelte Komponenten mit klar definierten Schnittstellen und nach Möglichkeit standardisierte Datenformate und Protokolle. Im Falle von hocheffizienten und spezialisierten Implementierungen in Fortran/C/C++ ermöglicht dies eine einfache Integration in Plattformen wie beispielsweise Python, .NET und Java in unterschiedlichen Anwendungsszenarien.

Ein wesentliches Verbesserungspotential im Zuge der inkrementellen Modernisierung bietet der kontinuierliche Ausbau der Testautomatisierung. Damit wird einerseits das Verhalten des aktuellen Systems dokumentiert und andererseits dienen die Tests als “Sicherheitsnetz”, um unbeabsichtigte Seiteneffekte und Fehler im Zuge von Änderungen automatisch erkennen zu können.

Im Zuge der konkreten Implementierung von Änderungen und Erweiterungen bieten sich natürlich zahlreiche Chancen, um von der Weiterentwicklung moderner Programmiersprachen und Bibliotheken zu profitieren und damit die Software wartungsfreundlicher, robuster und performanter zu gestalten. Gerade im Hinblick auf die Performance gab es in den letzten Jahren viele Verbesserungen (Parallelisierung etc.) von denen man häufig unmittelbar profitiert. Darüber hinaus können oft auch Teile der Eigenentwicklung ersetzt werden, weil diese entsprechende Funktionalität in der Zwischenzeit direkt unterstützt wird oder entsprechende Open Source Alternativen verfügbar sind. Technisch anspruchsvolle Aufgabenstellungen mit komplexen Berechnungen können damit schneller gelöst werden (Strong Scaling) bzw. man kann größere Problemstellungen lösen (Weak Scaling).

Zusätzlich zu der angeführten Modernisierung auf Produktebenen sollten natürlich auch gesamte Softwareentwicklungsprozess analysiert und gegebenenfalls verbessert / modernisiert werden. In den letzten Jahre wurde im Rahmen von Studien deutlich gezeigt, dass insbesondere die rasche Änderbarkeit (inkl. Rollout) von Software ein guter Indikator ist – nicht nur für die Leistungsfähigkeit der Softwareentwicklung, sondern aufgrund der zunehmenden Bedeutung von Software meist sogar für den gesamten wirtschaftlichen Erfolg eines Unternehmens. Wir, die RISC-Software GmbH, als langjähriger Entwicklungspartner großer industrieller Softwaresysteme unterstützen und forcieren daher auch die Modernisierung des Softwareentwicklungsprozesses bei unseren Partnerunternehmen.


Profitieren Sie von den Potenzialen von modernem C++

Die Entwicklung vieler großer Softwaresysteme startete im Laufe der 90er Jahre. Zu diesem Zeitpunkt gab es im Vergleich zu heute wesentlich weniger Programmiersprachen, OpenSource war in der Breite noch kaum ein Thema und die Anzahl der verfügbaren Bibliotheken war überschaubar. C++ war die Programmiersprache der Wahl für anspruchsvolle moderne (industrielle) Anwendungen. Zu diesem Zeitpunkt war der erste C++ Standard noch in Arbeit und existierende Implementierungen waren fragmentiert. Standardfunktionalität wie beispielsweise Container wurden individuell nach unterschiedlichen Designphilosophien entwickelt, weil moderne Alternativen wie die STL noch nicht bekannt bzw. verbreitet waren.

Während sich in den 2000er Jahren zahlreiche neue, moderne Programmiersprachen etablierten, schien die Entwicklung von C++ zu stagnieren. Nach der Veröffentlichung von C++ 98 begannen zwar die Arbeiten an der Nachfolgeversion – die Fertigstellung verzögerte sich allerdings bis 2011. Um weitere lange Phase der Stagnation zu verhindern, wechselte das C++ Komitee seinen Veröffentlichungsprozess und liefert alle 3 Jahre einen neuen Standard. Die Resonanz auf neue C++ Versionen ist überaus positiv – immer mehr Unternehmen beteiligen sich aktiv an der Weiterentwicklung dieser leistungsfähigen Sprache. Die RISC Software GmbH ist mit Michael Hava über das ASI (https://www.austrian-standards.at/) im Komitee vertreten.

Dem C++ Komitee ist es gelungen, die Lesbarkeit, Robustheit und Performance in weiten Bereichen wesentlich zu verbessern, ohne bestehenden Code zu brechen. Anwendungen profitieren daher ohne langwierigen/teuren Rewrite unmittelbar von den Verbesserungen und können inkrementell auf Modern C++ “portiert” werden. Während vorhandener Code nach wie vor funktioniert, bietet sich die Möglichkeit Quelltexte schrittweise lokal zu verbessern.
Untenstehend einige Beispiele um zu zeigen, was im Rahmen von lokalen Verbesserungen in Hinblick auf Kompaktheit, Ausdrucksstärke, Robustheit und Effizienz möglich ist.
 

Ressourcenmanagement (RAII)

Untenstehendes Beispiel demonstriert Verbesserungspotentiale im Hinblick auf #Resourcenmanagement, #Lesbarkeit, #Robustheit, #Kompaktheit


Lambdas

Untenstehendes Beispiel demonstriert Verbesserungspotentiale im Hinblick auf #Kompaktheit, #Lesbarkeit


Parallelisierung

Untenstehendes Beispiel demonstriert Verbesserungspotentiale im Hinblick auf #Parallelisierung, #Ausdrucksstärke, #Kompaktheit, #Lesbarkeit, #Robustheit


Für unsere Kunden haben wir schon viel erreicht

Wir besitzen langjährige Erfahrung in der Entwicklung nativer Software-Systeme in technischen Anwendungen. Diese sind häufig sehr komplex und haben hohe Anforderungen hinsichtlich Robustheit, Zuverlässigkeit und Determinismus der Ergebnisse/Zeit. Zu unseren Kunden zählen Airbus, WFL, DS-Automotion und zahlreiche andere, mit denen wir oftmals in langjährigen Entwicklungspartnerschaften zusammenarbeiten. Unser Dienstleistungsspektrum erstreckt sich über die Entwicklung neuer Systeme, das Re-Engineering bestehender Systeme bis hin zum Consulting und zu Schulungen.


Entwicklung der Software Bibliothek VML (Virtual Modeling Library)

Die VML (https://virtual-modeling.at) ist eine Software Bibliothek der RISC Software GmbH, welche neue Algorithmen zur exakten geometrischen Modellierung von Festkörpern implementiert. Sie unterstützt an Constructive Solid Geometry (CSG) angelehnte Operationen und die Hüllvolumenberechnung. Die VML bietet eine gute Skalierbarkeit bezüglich der Anzahl der bei der Modellierung durchgeführten Operationen. Die Bibliothek ist bestens für industrielle Anwendungen geeignet, welche kombinierte Anforderungen hinsichtlich geometrischer Genauigkeit, Geschwindigkeit und Skalierbarkeit aufweisen. Um die hohe Effizienz sicherzustellen, ist die VML in C++ implementiert und verwendet parallele Algorithmen, welche das Potential moderner Hardware-Architekturen wie Multi-Core Central Processing Units (CPUs) und Graphic Processing Units (GPUs) ausnutzen. Die VML kommt z.B. bei dem Produkt CrashGuard Studio der Firma WLF Millturn Technologies (https://www.wfl.at) zum Einsatz. CrashGuard Studio ist eine 3D-Simulationssoftware für multifunktionale CNC-Dreh-Bohr-Fräszentren, die es ermöglicht, Maschinen mit ihrer komplexen Kinematik und den umfangreichen Bearbeitungs- und Erweiterungsmöglichkeiten sehr realitätsgetreu nachzubilden.


Re-Engineering des Strukturoptimierungssystems Lagrange

Airbus Defence and Space setzt das multidisziplinäre Strukturoptimierungssystem Lagrange im Bereich des Engineering von Flugzeugstrukturen ein und startet dessen Entwicklung Anfang der 80er Jahre in der Programmiersprache Fortran77. Die RISC Software GmbH startete das Re-Engineering dieses Software-Systems im Jahr 2005. Im ersten Schritt ging es um das Ersetzen einer kritischen Berechnungskomponente, um deren Limitierung hinsichtlich der maximalen Problemgrößen aufzuheben. Dabei erfolgte die Neuentwicklung in C++ und wurde in das Alt-System integriert. In einem nächsten Schritt wurde das Gesamtsystem vom alten Fortran 77 Sprachstandard auf den neueren Fortran 2003/2008 portiert. Da das Gesamtsystem an vielen Stellen Limitierungen hinsichtlich der maximalen Problemgrößen aufwies und die Erweiterbarkeit aufgrund des Designs nur eingeschränkt gegeben war, wurde ein inkrementelles Re-Engineering des Gesamtsystems in Fortran 2003/2008 durchgeführt. Dabei sollte das neue System auch jederzeit im Produktivbetrieb verwendet werden können und die gleichen Ergebnisse wie das Alt-System liefern.


Consulting für Optimierungsmaßnahmen einer Schmierfilmberechnungsroutine

Die FH Wels entwickelte im Rahmen eines Simulationssystems eine Routine für die Berechnung des elastohydrodynamischen Drucks, welcher im Ölfilm zwischen Kolben und Zylinder im einem Verbrennungsmotor auftritt. Die RISC Software GmbH führte ein Consulting für Optimierungsmaßnahmen dieser in C++ implementierten Berechnungsroutine durch. Dabei sollte das Potential moderner Hardware-Architekturen bestmöglich ausgenutzt werden. Durch eine Analyse des Systems konnten die kritischen Punkte identifiziert und geeignete Optimierungsmaßnahmen erarbeitet werden. Abschließend wurde im Rahmen eines Workshops die Vorgehensweise und die Ergebnisse vermittelt.

www.risc-software.at

Abbildung 1: Vorzeitiges Lebensende von Software aufgrund technischer Schulden © RISC Software GmbH
Abbildung 1: Vorzeitiges Lebensende von Software aufgrund technischer Schulden © RISC Software GmbH
Abbildung 2: Kategorisierung von Re-Engineering Maßnahmen © RISC Software GmbH
Abbildung 2: Kategorisierung von Re-Engineering Maßnahmen © RISC Software GmbH
Abbildung 3: Schrittweise Migration von der Legacy zur neuen Anwendung mit Hilfe von Anti-Corruption Layer © RISC Software GmbH
Abbildung 3: Schrittweise Migration von der Legacy zur neuen Anwendung mit Hilfe von Anti-Corruption Layer © RISC Software GmbH
Ressourcenmanagement (RAII) © RISC Software GmbH
Ressourcenmanagement (RAII) © RISC Software GmbH
Lambdas © RISC Software GmbH
Lambdas © RISC Software GmbH
Parallelisierung © RISC Software GmbH
Parallelisierung © RISC Software GmbH