Wiederverwendbare Softwaremodule: Anpassbare Software geschickt umsetzen

Autor / Redakteur: Martin Becker und Bo Zhang* / Sebastian Gerstl |

Bei der erfolgreichen Realisierung von wiederverwendbaren und konfigurierbaren Softwaremodulen ist einer der wichtigsten Schritte die Auswahl von geeigneten Variabilitätsmechanismen. Prominente Vertreter sind hier die bedingte Kompilierung mit dem Präprozessor, die Modulauswahl oder die Parametrierung in Verbindung mit bedingter Ausführung.

Anbieter zum Thema

Software-Module aus früheren Entwicklungsprojekten wiederzuverwenden mag verlockend und einfach klingen. Werden diese Software-Varianten aber unsauber oder unzulänglich übernommen, führt das schnell zu ausuferdner Komplexität Welche Stolperfallen ergeben sich beim Einsatz wiederverwendbarer bzw konfigurierbarer Software-Module, und wie lassen sich diese am Geschicktesten verwenden?
Software-Module aus früheren Entwicklungsprojekten wiederzuverwenden mag verlockend und einfach klingen. Werden diese Software-Varianten aber unsauber oder unzulänglich übernommen, führt das schnell zu ausuferdner Komplexität Welche Stolperfallen ergeben sich beim Einsatz wiederverwendbarer bzw konfigurierbarer Software-Module, und wie lassen sich diese am Geschicktesten verwenden?
(Bild: gemeinfrei / CC0 )

Der Blick in den Entwicklungsalltag zeigt, dass die Mechanismen oftmals leichtfertig ausgewählt und willkürlich eingesetzt werden. Die Konsequenz sind dann oftmals schlecht verständliche und wartbare Software-Ungetüme. Der Beitrag gibt einen Überblick über gängige Variabilitätsmechanismen, zeigt Stolperfallen und Best-Practices anhand von Praxisbeispielen auf.

Variabilitätstreiber in eingebetteten Systemen

Der Bedarf an kundenspezifischen Software-Lösungen steigt ungebremst. Haupttreiber hinter den angebotenen Produktvarianten sind dabei in erster Linie die unterschiedlichen Kundenbedürfnisse, der technologische Wandel, z.B. neue Mehrkern-Prozessoren, und der Kostendruck. Diese Treiber lassen sich in der Regel nur begrenzt beeinflussen, wodurch die Vermeidung entsprechender Varianten oftmals schwer fällt.

Bildergalerie

Gerade für den Software-Anteil der eingebetteten Systeme herrscht die Meinung vor, dass dieser schnell und kostengünstig an neue Gegebenheiten angepasst werden kann, was im Vergleich zur Hardware aufgrund der äußerst geringen Produktionskosten zunächst auch richtig ist. Naheliegender weise versucht man die erforderlichen Anpassungen also in die Software zu verlagern. Dies führt dann im Laufe der Zeit recht schnell zur hochgradig anpassbaren, konfigurierbaren und parametrierbaren Softwarelösungen, die immer schwerer zu warten und zu konfigurieren sind. Viele Embedded Software Entwickler haben diese Präprozessor- oder Makefile-Hölle in der einen oder anderen Form schon am eigenen Leib gespürt.

Variabilitätsmechanismen im Vergleich

Die Unterschiede in den Produktvarianten lassen sich auf unterschiedliche Arten realisierten. Man spricht in diesem Zusammenhang von Variabilitätsmechanismen. Prominente Vertreter sind hier die bedingte Kompilierung mit dem Präprozessor, die Modulauswahl oder die Parametrierung in Verbindung mit bedingter Ausführung. Mit den Variabilitätsmechanismen lassen sich also die variablen Produktmerkmale im Quellcode und anderen Entwicklungsartefakten (z.B. Testfälle, Anforderungen, Design-Modelle) umsetzen.

Um eine wohlüberlegte Auswahl der Variabilitätsmechanismen zu fördern, stellen wir in der nachfolgenden Übersicht (siehe Tabelle 1) typische Variabilitätsmechanismen vor und charakterisieren diese entlang zentraler Eigenschaften. Der Vergleich basiert auf entsprechenden Übersichten [1][2][5][6], die in der Software Product Line Engineering Community über die letzten beiden Jahrzehnte entstanden sind.

Gemäß unserer industriellen Erfahrung und jüngsten Studien [3][4][7][8] werden im Kontext von Embedded Software insbesondere folgende Mechanismen zur Realisierung von Software-Varianten eingesetzt:

  • Cloning. Softwarestände werden zwischen verschiedenen Projekten kopiert und anschließend modifiziert.
  • Bedingte Kompilierung. Mit dem C-Präprozessor werden Code-Blöcke per Schalter ein-/ausgeblendet.
  • Bedingte Ausführung. Über Kontrollkonstrukte der Programmiersprachen werden Code-Blöcke über Variablen (Parameter) gesteuert aktiviert/deaktiviert.
  • Modulaustausch. Build-Systeme, wie zum Beispiel make, ermöglichen die Auswahl von Modulen, die beim Bauen zum Einsatz kommen.

Weiterhin finden sich noch folgende Mechanismen in der industriellen Praxis:

  • Polymorphismus. Sprachkonstrukte wie Funktionszeiger, Überladung oder virtuelle Methoden können verwendet werden, um in der Laufzeit zwischen unterschiedlichen Realisierung auszuwählen.
  • Aspekt Orientierung. Über entsprechende Weaver (für C, Java) lassen sich variable Aspekte nachträglich in Komponenten einweben.
  • Frame Technology. Unter Verwendung dedizierter Präprozessoren lässt sich die zu bauende Software in einem Vorverarbeitungsschritt gezielt anpassen. Ein prominenter Vertreter ist hier die Frame Technology von Paul Basset.

Bei der Auswahl von Mechanismen sollten folgende generelle Aspekte berücksichtigt werden:

  • Bindezeit: Wann wird die Variabilität gebunden, d.h. wann wird die konkrete Variante in den Artefakten gebildet?
  • Granularität: Wie fein können die Änderungen sein, die zwischen den Varianten durchzuführen sind, z.B. einzelne Zeilen, Blöcke, Dateien, Module, Subsysteme?
  • Explizite Variationspunkte: Lassen sich die Stellen, in denen sich die Varianten unterscheiden, einfach lokalisieren und mit den entsprechenden variablen Merkmalen in Verbindung bringen?
  • Varianten-Isolation. Ist die Realisierung einer einzelnen Variante isoliert von den restlichen oder befinden sich alle Varianten innerhalb einer Datei?
  • Offene Variation. Lassen sich neue Varianten hinzufügen, ohne dass dies einen Einfluss auf existierende Varianten hat?
  • Nicht-Code-Artefakte. Kann der Mechanismus auch jenseits von Code eingesetzt werden?
  • Default-Werte. Werden Default-Realisierungen unterstützt?

Die obigen Mechanismen lassen sich bezüglich ihrer Eigenschaften wie folgt charakterisieren.

Praktische Erfahrungen mit Variabilitätsmechanismen

In diesem Abschnitt wird die Verwendung der Variabilitätsmechanismen in der Praxis näher beleuchtet sowie deren praktische Vorteile und Herausforderungen diskutiert und entsprechende Empfehlungen gegeben. Vorteile, Herausforderungen und Empfehlungen sind in Tabelle 2 aufgelistet. Generell lässt sich sagen, dass in der Vergangenheit aufgrund der Ressourcenbeschränkungen vermehrt auf Bedingte Kompilierung und Modulaustausch gesetzt wurde.

Im zunehmenden Maße wird Variabilität aufgrund der höheren Flexibilität, neuer Geschäftsmodelle und des geringeren Management-Aufwandes in die Laufzeit verlagert. Dabei kommen neben Polymorphismus und Bedingter Ausführung vor allem auch entsprechende Lifecycle-Management-Frameworks wie beispielsweise OSGI zum Einsatz. Egal welche Mechanismen zum Einsatz kommen, achten Sie darauf, dass die Variationspunkte einfach lokalisieren lassen und sich auf die zugrunde liegenden Variabilitäten zurückverfolgen lassen. Damit erleichtern Sie das Varianten-/ Variabilitätsmanagement ungemein und ermöglichen toolgestützte Analysen und Verbesserungen.

Zusammenfassung

Unzulängliche Realisierung von Software-Varianten führt schnell zu unnötiger Komplexität und sollte nach Möglichkeit frühzeitig vermieden werden. In diesem Beitrag haben wir einen Überblick über gängige Variabilitätsmechanismen gegeben und Stolperfallen und Best-Practices aufgezeigt. Der Beitrag ist als Orientierungshilfe gedacht.

Literatur- und Quellenverzeichnis

[1] S. Apel, D. Batory, C. Kästner, G. Saake, “Feature-Oriented Software Product Lines”, Springer, 2013.
[2] F. Bachmann and P. Clements, "Variability in software product lines", Software Engineering Institute, Pittsburgh, USA, Tech. Rep. CMU/SEI-2005-TR-012, Sep. 2005.
[3] Y. Dubinsky, J. Rubin, T. Berger, S. Duszynski, M. Becker, K. Czarnecki, 0“An Exploratory Study of Cloning in Industrial Software Product Lines”, Proceedings of the 17th European Conference on Software Maintenance and Reengineering, 2013.
[4] S. Duszynski, “Analyzing Similarity of Cloned Software Variants using Hierarchical Set Models”, Dissertation, Fraunhofer IESE, Kaiserslautern, Germany, 2015.
[5] C. Gacek and M. Anastasopoulos, "Implementing product line variabilities," SIGSOFT Softw. Eng. Notes, vol. 26, no. 3, pp. 109-117, May 2001.
[6] T. Patzke, "Sustainable Evolution of Product Line Infrastructure Code," Dissertation, Fraunhofer IESE, Kaiserslautern, Germany, 2011.
[7] B. Zhang, M. Becker, T. Patzke, K. Sierszecki, and J. E. Savolainen, "Variability evolution and erosion in industrial product lines: a case study", 17th International Software Product Line Conference (SPLC 2013), pp. 168—177.
[8] B. Zhang, "VITAL - reengineering variability specifications and realizations in software product lines", Dissertation, Fraunhofer IESE, Kaiserslautern, Germany, 2015.

(Dieser Beitrag wurde mit freundlicher Genehmigung der Autoren dem Tagungsband Embedded Software Engineering Kongress 2016 entnommen.)

* Dr. Martin Becker ist Informatiker und leitet die Abteilung Embedded Systems Engineering am Fraunhofer IESE. In einer Vielzahl von Forschungs- und Industrieprojekten hat er in den letzten 15 Jahren vielfältige Erfahrungen mit Varianten-Management in verschiedenen Anwendungsgebieten gesammelt, sowie neue Methoden, Techniken und Werkzeuge auf diesem Gebiet entwickelt.

* Bo Zhang ist ein wissenschaftlicher Mitarbeiter am Fraunhofer Institut für Experimentelles Software Engineering (IESE) in Kaiserslautern. Er arbeitet in der Embedded Systemen Entwicklung Abteilung und seiner Forschung konzentriert sich auf die modellbasierte Systemarchitektur Engineering und Variationsmangement.

(ID:44852333)