Forschung und Lehre Architektur- und Code-Management von Software-Varianten

Autor / Redakteur: Prof. Dr. Rainer Koschke, Universität Bremen* / Martina Hafner

Dieser Artikel beschreibt Techniken, um Software-Varianten, die durch ungeplante Wiederverwendung entstanden sind, zu konsolidieren und in eine Produktlinienplattform zu integrieren, um so Wartungs- und Weiterentwicklungskosten einzusparen. Die Techniken stammen aus der Forschung und wurden in industriellen Fallstudien bei der Robert-Bosch GmbH erprobt.

Anbieter zum Thema

Bei Software-Herstellern im Bereich eingebetteter Systeme, deren Produkte große Gemeinsamkeiten, aber auch Spezifika aufweisen, entstehen häufig Software-Varianten durch ungeplante Wiederverwendung. Der Code eines Produkts wird für ein anderes Produkt kopiert und an die Anforderungen des neuen Einsatzes angepasst. Die resultierenden Varianten erfahren eine eigene Weiterentwicklung. Bei einer großen Zahl von Varianten erhöhen sich dabei die Wartungskosten, weil notwendige Änderungen im gemeinsamen Code, z.B. zur Fehlerbehebung, in allen Varianten individuell analysiert, nachgezogen, dokumentiert und getestet werden müssen. Die Wartung und Weiterentwicklung einer großen Anzahl von Varianten ist auf Dauer kaum mehr beherrschbar.

13107990

Die Wiederverwendung vorhandener Software-Komponenten wird - neben generativen Ansätzen - grundsätzlich als aussichtsreichster Weg gesehen, um Ziele wie Time-to-Market“ bzw. „Time-to-Delivery“, niedrige Entwicklungskosten, hohe Software-Qualität, niedrige Wartungs- und Evolutionskosten und hohe Vorhersagbarkeit bei Projektablauf und Qualität zu realisieren. Opportunistische, weitgehend ungeplante Wiederverwendung hat sich aber als ungeeigneter Weg erwiesen. Vielmehr ist eine aktive Gestaltung der wiederverwendbaren Komponenten notwendig, die auch Variabilität zur Anpassung an die spezifischen Erfordernisse des Einzelprodukts vorsieht.

Software-Varianten konsolidieren

Softwareproduktlinien sind Familien von Softwaresystemen, bei denen die Gemeinsamkeiten der von den Systemen zur Verfügung gestellten Funktionen die Unterschiede deutlich überwiegen. Sie können effizient implementiert werden, indem sie eine gemeinsame Codebasis wiederverwenden. Oft organisiert man die Implementierung in einen gemeinsamen Kern aller Systeme sowie in die produktspezifischen Erweiterungen.

Speziell für Firmen, deren einzelne Softwareprodukte große Gemeinsamkeiten aufweisen, liegt dieser Weg nahe. Andererseits scheuen viele Firmen diesen Weg, weil sie bereits beträchtliche Summen Geld in die Entwicklung ihrer Einzelsysteme investiert haben. Sie können es sich nicht leisten, eine neue Software-Produktlinie aufzusetzen, ohne existierende Implementierungen einzubeziehen. Dies würde zu viel Entwicklungszeit verlangen und ein zu hohes Risiko darstellen. Ein gangbarer Weg ist es, die Produktlinie stattdessen evolutionär und inkrementell einzuführen, indem existierende System konsolidiert und schrittweise in eine Produktlinie integriert werden. Hierzu werden Techniken für die Analyse existierender Software-Varianten benötigt.

Durch kontrolliertes Management von Varianten in Software-Produktlinien können die Probleme der Variantenbildung vermieden werden. Jedoch müssen hierzu die existierenden Varianten erst zu einer Produktlinie konsolidiert werden. Dazu müssen Gemeinsamkeiten und Unterschiede der Varianten – Variabilitäten genannt – identifiziert werden.

Im Folgenden werden erste Ergebnisse unserer Forschung vorgestellt, die Methoden und Techniken erarbeitet, um existierende Software-Varianten in Software-Produktlinien zu konsolidieren. Wir untersuchen dieses Problem sowohl auf der Quellcodeebene als auch auf der Architekturebene. Hierbei bauen wir auf einer Reihe von Techniken auf, die wir bereits erfolgreich für die Analyse einzelner Systeme eingesetzt haben. Dazu zählen insbesondere Klonerkennung und reflexionsbasierte Architekturrekonstruktion. Diese Techniken adaptieren und erweitern wir für eine inkrementelle Untersuchung von Varianten.

Das Ziel dieser Erweiterung ist die Unterstützung eines inkrementellen Vorgehens, bei dem zu einem Zeitpunkt, an dem bereits n Systeme untersucht wurden, nur die Unterschiede des nächsten Systems n+1 zu den bisherigen n Systemen gezielt analysiert werden müssen.

Welche Komponenten der Varianten korrespondieren?

Beim Vergleich zweier Varianten stellt sich zunächst die Frage, welche Komponenten der Varianten miteinander korrespondieren. Da wir von Varianten ausgehen, die einer gemeinsamen Code-Basis entstammen, können hier Korrespondenzen über Namen und syntaktische Übereinstimmungen hergestellt werden. Für letztere können Techniken zur Klonerkennung herangezogen werden. Die Klonerkennung findet gleichen und ähnlichen Code zwischen Varianten. Allerdings ist auch der Fall zu erwarten, dass Komponenten in einer Variante komplett re-implementiert wurden. In diesem Fall müssen die Schnittstellen manuell aufeinander abgebildet werden. Letztlich lässt sich nicht automatisch entscheiden, ob zwei Komponenten dieselbe Semantik haben, so dass hierfür auch eine Einbeziehung des Benutzers von Nöten ist.

Architektur aus der Implementierung rekonstruieren

Für große Varianten interessieren nicht nur die Unterschiede und Gemeinsamkeiten auf der Code- sondern auch auf der Architekturebene. Um Unterschiede und Gemeinsamkeiten zwischen Architekturen von Varianten zu finden, müssen entsprechende Architekturbeschreibungen für die Varianten existieren. Dies ist in der Praxis selten der Fall.

Bild 1: Zusammenhang der Ebenen Implementierung, Produktarchitektur und Produktlinienarchitektur und die Techniken für die jeweiligen Abbildungen; Abbildungen sind durch Farben ausgedrückt. (Archiv: Vogel Business Media)

Die von Murphy (2001) entwickelte Reflexionsmethode ist ein leichtgewichtiger Ansatz, um die statische Architektur für ein System aus der Implementierung zu rekonstruieren. Hierbei kann zunächst eine Hypothese für die erwartete Architektur aufgestellt werden. Dabei werden in einer hypothetischen Architektur die Architekturkomponenten und deren zu erwartende Abhängigkeiten angegeben (vergleiche Abbildung 1). Tatsächliche Komponenten – wie Funktionen, Dateien, Klassen oder Packages – und ihre Abhängigkeiten können aus dem Code automatisch hergeleitet werden. In einem dritten Schritt werden die tatsächlichen Komponenten der Implementierung auf die in der hypothetischen Architektur manuell abgebildet. Durch automatischen Abgleich der extrahierten tatsächlichen Abhängigkeiten zwischen den Implementierungskomponenten lassen sich dank dieser Abbildung Unterschiede von Erwartung und Ist feststellen.

Die Reflexionsmethode haben wir für Software-Varianten erweitert (Frenzel, 2007). Hierzu sind sowohl konzeptuelle Erweiterungen an der Ausdrucksmächtigkeit für Soll-Architekturen (die in diesem Kontext zur Produktlinienarchitektur wird) als auch an der Abbildung der Implementierungskomponenten auf Komponenten der Produktlinienarchitektur notwendig.

Da die Abbildung von Implementierung auf die Architektur ein manueller und arbeitsintensiver Anteil ist, minimieren wir den Aufwand, indem wir nur die Unterschiede zwischen bereits betrachteten Varianten und der als nächstes zu analysierenden Variante neu analysieren. Hierbei nutzen wir die hohe Code-Ähnlichkeit zwischen Varianten aus. Wenn wir durch die Klonerkennung eine Korrespondenz zwischen zwei Implementierungsvarianten V1 und V2 identifiziert haben und wir bereits eine Abbildung von V1 auf eine Architekturkomponente A haben, können wir diese Abbildung für V2 übertragen. Sind V1 und V2 genau gleich, so wird auch V2 auf A abgebildet. Sind V1 und V2 nur ähnlich, wird V2 auf eine neue Architekturkomponente A‘ abgebildet, die eine Variante von A darstellt. Auf diese Weise entsteht inkrementell eine Beschreibung der Produktlinienarchitektur. Diesen Ansatz haben wir mit einer Produktlinie der Robert-Bosch GmbH evaluiert.

Konsolidierung

Auf Basis der identifizierten Gemeinsamkeiten und Unterschiede können die Varianten konsolidiert werden. Hierzu müssen geeignete Abstraktionen für die Unterschiede gefunden werden können. Die Implementierungsmechanismen für die Variabilitäten reichen von Macros, bedingter Übersetzung, Parametrisierung, Generizität, Komponenten, Entwurfsmuster, Polymorphismus bis hin zu generativer Programmierung.

Architekturmanagement von Produktlinien

Wenn die Konsolidierung abgeschlossen ist, muss darauf geachtet werden, dass die Varianten nicht wieder auseinander driften. Hierzu können wieder Klonerkennungstechniken kontinuierlich benutzt werden, die Ähnlichkeiten zwischen Varianten und Produktlinienkern identifizieren. Die gleichen Teile können dann in den Produktlinienkern gezogen werden. Dieses Vorgehen unterstützt die so genannte Grow-and-Prune-Methode, bei der Kopieren von Code benutzt wird, um explorativ Features zu implementieren bzw. wiederzuverwenden (Grow) und einer nachgeschalteten Konsolidierungsphase (Prune), in der im Falle eines Erfolgs die Redundanz weitgehend beseitigt wird (Mende, 2007).

Jetzt Newsletter abonnieren

Verpassen Sie nicht unsere besten Inhalte

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

(ID:299965)