Der Duden (24. Aufl.) macht zwischen »wieder verwenden« und »wiederverwenden« keinen Unterschied. Wir sehen das anders; wenn jemand einen alten Mantel nicht wegwirft, sondern einem neuen Besitzer übergibt, der ihn noch jahrelang trägt, dann wird der Mantel wieder verwendet, aber (nach unserem Verständnis) nicht wiederverwendet. Von Wiederverwendung sprechen wir nur bei immateriellen Gütern, vor allem bei Software.
Noch in den Achtzigerjahren war die Wiederverwendung ein klar definiertes, also abgegrenztes Teilgebiet des Software Engineerings; während immer wieder betont wurde, wie sinnvoll und vorteilhaft die Wiederverwendung sei, spielte sie praktisch doch nur eine Nebenrolle; am häufigsten fand Wiederverwendung lokal (also bei der Entwicklung von Varianten und Nachfolgesystemen) mittels Kopieren und Ändern (Copy and Edit) statt. Vor allem durch die Möglichkeiten der objektorientierten Programmierung ist die Bedeutung der Wiederverwendung seitdem ganz erheblich gewachsen, und eine klare Grenze zwischen Neuentwicklung und Wiederverwendung ist nicht mehr zu erkennen. Darum ist dieses Kapitel nur in Zusammenhang mit anderen Teilen des Buches, vor allem mit Kapitel 17 (Entwurf) zu sehen.
Hier führen wir die wichtigsten Begriffe der Wiederverwendung ein, diskutieren die Voraussetzungen, Vorteile und Schwierigkeiten und behandeln eine Reihe verschiedener Entwicklungstechniken für die Wiederverwendung. Das Kapitel schließt mit einem Versuch, einen Blick in die Zukunft der Wiederverwendung und damit der Software-Entwicklung allgemein zu werfen.
Wiederverwendung gibt es schon sehr viel länger, als es Software gibt, und in der Software sehr viel häufiger, als wir bemerken.
Historische Beispiele der Wiederverwendung sind:
Die Wiederverwendung musikalischer Werke oder ihrer Teile durch die Urheber selbst oder durch andere,
Reproduktionen und Abgüsse in der bildenden Kunst,
Zitate und Plagiate in der Literatur.
An diesen Beispielen sind einige Merkmale sichtbar, die wir auch bei der Wiederverwendung von Software finden:
1. Die Wiederverwendung spart Aufwand.
2. Die Wiederverwendung impliziert ein soziales Gefälle vom Urheber zum Wiederverwender. Sie setzt daher eine gewisse Achtung vor dem Urheber voraus.
3. Die Wiederverwendung kann die Qualität des Neuen günstig beeinflussen.
4. Das Plagiat, der geistige Diebstahl, ist eine wichtige, aber illegale Art der Wiederverwendung.
Auch Architekten und Ingenieure haben zu allen Zeiten Konstruktionen wiederverwendet. Im Software Engineering ist die Wiederverwendung aber besonders attraktiv, weil wir keine physischen Artefakte (wie Häuser oder Maschinen) produzieren müssen; bei der Software kann die Einsparung durch Wiederverwendung bis zu 100 % betragen.
Wie selbstverständlich uns allen die Wiederverwendung ist, zeigen einige Situationen, in denen wir kaum an Wiederverwendung denken:
a) Ein Schüler kauft ein Computerspiel.
b) Ein Programmierer verwendet in seinem Programm eine vom Betriebssystem bereitgestellte Sortierroutine.
c) Ein Entwickler schreibt in einer Eingaberoutine die Umwandlung von Zeichen in Zahlen. Er erinnert sich an all die ähnlichen Programme, die er im Laufe seiner Berufstätigkeit bereits geschrieben hat.
d) Ein technischer Redakteur beginnt die Arbeit an einem neuen Handbuch. Zunächst kopiert er das Inhaltsverzeichnis eines anderen Handbuchs in eine leere Datei.
e) Ein Wartungsprogrammierer ersetzt ein ganzes Subsystem, indem er eine Prozedur nach der anderen in einer modernen Programmiersprache neu codiert.
f) Ein Programmierer leitet aus einer bereits vorhandenen Klasse eine neue ab und definiert darin zusätzliche Merkmale und Methoden.
g) Die neue Version eines Programms wird mit den alten Testdatensätzen geprüft.
Die Wiederverwendung betrifft in diesen Beispielen (a) die gesamte Software, (b) eine bestimmte Prozedur, (c) den Algorithmus, (d) die Struktur eines Dokuments, (e) die Struktur des Codes, (f) die Definition eines Typs, (g) die Testdaten.
Wir wollen diese Beispiele nicht vertiefen, sondern nur darauf hinweisen, dass Wiederverwendung nicht erst erfunden werden muss, sie findet täglich und überall statt. Wir könnten aber noch größeren Nutzen durch Wiederverwendung erzielen, wenn wir sie bei der Entwicklung neuer Software stärker berücksichtigten.
Viele Menschen haben die naive Erwartung, dass Wiederverwendung zustande kommt, indem Entwickler zufällig oder gezielt Resultate früherer Arbeiten entdecken und verwenden. Das wäre vergleichbar mit der Wiederverwendung eines Briefes, den man früher einmal geschrieben hat, zu einem anderen Zeitpunkt, an einen anderen Adressaten und (wahrscheinlich) für einen anderen Zweck. Natürlich ist das nur in den seltensten Fällen möglich; in der Regel muss man zunächst aus einem Brief die Textbausteine isolieren, die wiederverwendbar sind, muss sie generalisieren und, wo nötig, die Spezialisierung durch Parameter vorsehen. Dann muss man die Bausteine in geeigneter Weise bereitstellen. Die Vorbereitung der Wiederverwendung ist sehr aufwändig, die Wiederverwendung selbst nur noch eine Kleinigkeit. Wir unterscheiden also im Zusammenhang mit der Wiederverwendung zwischen der Herstellung wiederverwendbarer Software-Einheiten auf der Seite des Gebers und ihrer Verwendung durch den Nehmer.
Bevor wir näher darauf eingehen, welche Formen der Wiederverwendung unterschieden werden können, wollen wir den Begriff Wiederverwendung (software reuse) klären. Mili et al. (2002) geben eine brauchbare prozessorientierte Definition an.
Software reuse is the process whereby an organization defines a set of systematic operating procedures to specify, produce, classify, retrieve, and adapt software artifacts for the purpose of using them in its development activities.
Mili et al. (2002)
Diese Definition charakterisiert den Prozess der Wiederverwendung: Damit Software-Einheiten wiederverwendet werden können, muss spezifiziert sein, was wiederverwendet werden soll, die entsprechenden Software-Einheiten müssen entwickelt und klassifiziert werden, damit sie wiedergefunden werden können. Im Zuge der Wiederverwendung müssen sie in der Regel angepasst werden.
Weil Wiederverwendung in der täglichen Praxis in verschiedenen Formen und Bedeutungen vorkommt, erscheint es uns sinnvoll, diese durch verschiedene Wörter zu bezeichnen. Einige Formen der Wiederverwendung sind uns mittlerweile so geläufig, dass wir sie nicht mehr bewusst wahrnehmen:
Wiederverwendung von Software-Produkten
Beispiel: In einem System verwenden wir ein eingekauftes Datenbanksystem, um die Daten persistent zu speichern.
Wiederverwendung von Lösungsstrukturen, Methoden und Sprachen
Beispiel: Beim Architekturentwurf konstruieren wir eine Komponente nach dem in Abschnitt 17.5.2 vorgestellten Beobachter-Entwurfsmuster.
Wiederverwendung von Komponenten, die in Programmgeneratoren, im Betriebssystem und in Bibliotheken stecken
Beispiel: Wir entscheiden uns bei einem System, das als EJB-Anwendung entwickelt wird, die persistente Speicherung der Daten nicht selbst zu programmieren, sondern die von der EJB-Anwendungsumgebung zur Verfügung gestellten Mechanismen und Komponenten zu verwenden.
Die Wiederverwendung im üblichen engeren Sinne unterscheidet sich von diesen allgemeinen Formen der Wiederverwendung dadurch, dass
eine Wahlmöglichkeit zwischen Wiederverwendung und Neuentwicklung besteht,
eine Anpassung der wiederverwendbaren Komponente vorgesehen und in der Regel notwendig ist.
Die erste Voraussetzung besteht beispielsweise bei Editoren und Compilern nicht, denn es ist in aller Regel unsinnig, eine Eigenentwicklung in Betracht zu ziehen. Eine Anpassung ist weder möglich noch erforderlich, wenn wir Grundfunktionen aus dem Betriebssystem in Anspruch nehmen.
Wiederverwendung setzt voraus, dass wiederverwendbare Software-Einheiten vorhanden sind. Die IEEE-Norm definiert Wiederverwendbarkeit (reusability) wie folgt:
reusability — The degree to which a software module or other work product can be used in more than one computer program or software system.
IEEE Std 610.12 (1990)
Wiederverwendbarkeit von Software-Einheiten ist also ein Qualitätsmerkmal, aber kein einfaches, wie das Wort »degree« suggerieren könnte, sondern eines, das aus mehreren Aspekten zusammengesetzt ist. Natürlich ist die Wiederverwendbarkeit in der Regel sehr viel höher, wenn die Wiederverwendung bereits eingeplant war.
Wir sprechen von ungeplanter Wiederverwendung, wenn eine Komponente erst nach ihrer Entwicklung für die Wiederverwendung entdeckt wird. Sie muss dann in der Regel geändert und verbessert werden, damit sie die Anforderungen an eine wiederverwendbare Komponente erfüllt.
Bei der geplanten Wiederverwendung werden Komponenten mit dem Ziel entwickelt, dass sie wiederverwendet werden sollen. Es können zwei Szenarien unterschieden werden: Standardkomponenten stellen Funktionalität bereit, die bei einem großen Spektrum von Software-Systemen benötigt wird. Sie werden ausschließlich entwickelt, um wiederverwendet zu werden. Beispiele sind Bibliotheken für Bedienoberflächen oder für Datenstrukturen.
Spezialkomponenten werden für eine bestimmte Aufgabe entwickelt, aber die Wiederverwendung ist von Beginn an ein wichtiges Ziel. Deshalb muss sichergestellt werden, dass diese Komponenten allgemein benutzt werden können, von hoher Qualität und besonders gut dokumentiert sind.
Zwei wichtige Aspekte sind das Einsatzspektrum und der Anpassungsaufwand.
Kann eine Software-Einheit nur in einem engen Anwendungsbereich (z. B. für ein Nachfolgesystem) wiederverwendet werden, dann spricht man von einem schmalen, sonst von einem breiten Einsatzspektrum.
Kann eine Software-Einheit so, wie sie vorliegt, oder durch einfache Parametrisierung angepasst verwendet werden, dann entsteht kein oder nur geringer Anpassungsaufwand. Muss sie (z. B. durch Vererbung und Programmierung) angepasst werden, dann entsteht höherer oder hoher Anpassungsaufwand.
Eine ähnliche Betrachtung stellen Siedersleben und Meyer (2000) an: Sie ordnen die Software-Einheiten nach den Kriterien »Fachliche Funktionalität« und »Realisierungstechnik« ein. Abbildung 24–1 zeigt diesen Zusammenhang.
Abb. 24–1 Wiederverwendungspotenzial von Software-Einheiten
Software-Einheiten, die weder anwendungsspezifisch noch technikspezifisch sind, können als Bibliothekseinheiten in vielen verschiedenen Entwicklungen wiederverwendet werden. Einheiten, die eine bestimmte fachliche Funktionalität realisieren, und Einheiten, die eine bestimmte Realisierungstechnik kapseln, sind immer dann wiederverwendbar, wenn die gleiche Funktionalität bzw. die gleiche Realisierungstechnik benötigt wird. Software-Einheiten, die zugleich anwendungs- und technikspezifisch sind, sind zu vermeiden, denn sie erschweren Änderungen und lassen sich kaum wiederverwenden.
Die Wiederverwendung kann man auch nach anderen Aspekten gliedern:
Die Gegenstände der Wiederverwendung können sehr verschieden sein. Wie die Beispiele in Abschnitt 24.1.2 zeigen, können z. B. Ideen, Konstruktionen, Methoden, Notationen, Strukturen, Spezifikationen, Entwürfe, Quellcode, Maschinen-Code, Testdaten, Handbücher, Formulare wiederverwendet werden. Dabei kann es sich jeweils um eigene oder fremde Ergebnisse handeln.
Die Granularität der Wiederverwendung kann variieren. Eine wiederverwendbare Software-Einheit wird in der Regel als Ganzes genutzt (z. B. ein Rahmenwerk). Möglich ist aber auch, dass einzelne ihrer Bestandteile separat wiederverwendet werden (z. B. einzelne Klassen einer Klassenbibliothek).
Die Einheit selbst kann relativ klein oder sehr groß sein. Die Untergrenze ist erreicht, wenn der Aufwand zur Wiederverwendung den zur Neuschöpfung deutlich übersteigt. Die Obergrenze ist durch die Komplexität und die damit verbundene Spezialisierung der Software gegeben. Ein extrem komplexes System ist kaum ein zweites Mal einsetzbar.
Abbildung 24–2 zeigt ganz unterschiedliche Beispiele für die Wiederverwendung, platziert in einer Ebene, die vertikal nach dem Anpassungsaufwand, horizontal nach den Entwicklungsschritten gegliedert ist.
Abb. 24–2 Landschaft der Wiederverwendung
Wiederverwendbare Software-Einheiten zu erstellen, ist anspruchsvoll und aufwändig. Wiederverwendung sollte aus ökonomischer Sicht nur dann angestrebt werden, wenn der Nutzen der Wiederverwendung die Kosten übersteigt.
Die Kosten setzen sich nach Mili, Mili und Mili (1995) zusammen aus
dem Mehraufwand, um eine wiederverwendbare Software-Einheit zu entwickeln,
den Kosten, um Einheit in einem Repository abzulegen und zu verwalten,
den Kosten, um die Software-Einheit zu finden, anzupassen und zu integrieren.
Die Angaben zu den Mehrkosten variieren erheblich. So geben beispielsweise Poulin und Caruso (1993) an, dass etwa 50 % Mehraufwand benötigt wird, um eine Software-Einheit wiederverwendbar zu entwickeln. Tracz (1994) nennt, vorsichtig geschätzt, 55 % Mehrkosten1, die sich folgendermaßen aufteilen: 25 % für zusätzliche Verallgemeinerung (d. h. für die Beseitigung von Merkmalen, die auf einen speziellen Einsatz zugeschnitten sind), 15 % für zusätzliche Dokumentation, 10 % für zusätzliches Testen und 5 % für die Ablage der Einheit in einem Repository und für die Wartung. Margono und Rhoads (1992) gehen dagegen von 100 % Mehrkosten aus (15 % in der Analyse, 60 % im Entwurf und 25 % im Test).
Über die Kosten, die entstehen, um eine wiederverwendbare Software-Einheit anzupassen, gibt es in der Literatur nur wenige Zahlen. Boehm et al. (2000) stellen auf der Basis der in Selby (1988) publizierten Studie den in Abbildung 24–3 dargestellten Zusammenhang zwischen dem Umfang der Anpassungen und den Kosten der Wiederverwendung auf.
Abb. 24–3 Anpassungskosten bei der Wiederverwendung (nach Boehm et al., 2000, S. 21)
Die Abbildung zeigt, dass die Kosten der Anpassung sehr rasch steigen, wenn der Umfang der Anpassung zunimmt. Müssen – wie dargestellt – ca. 14 % einer Software-Einheit angepasst werden, so werden dadurch bereits 55 % der Kosten verursacht, die eine Neuentwicklung benötigen würde. Boehm et al. sagen in diesem Zusammenhang auch, dass es sich hier um ein sehr günstiges Szenario handelt, im ungünstigen Fall können die Kosten der Anpassung die Kosten einer Neuentwicklung deutlich übersteigen. Man kann daraus schließen, dass sich die Wiederverwendung nur lohnt, wenn nur sehr wenig angepasst werden muss. Poulin, Caruso und Hancock (1993) geben 20 % der Entwicklungskosten als mittlere Anpassungskosten bei der Wiederverwendung an. Selbst eine Wiederverwendung ganz ohne Anpassung ist nicht kostenlos, weil in jedem Fall ein Aufwand von ca. 5 % für Verwaltung und Suche der wiederverwendbaren Komponenten entsteht.
Beim Nutzen der Wiederverwendung sind zwei Aspekte zu betrachten, die eingesparten Entwicklungskosten und der Nutzen, der sich daraus ergibt, dass eine wiederverwendbare Software-Einheit in aller Regel qualitativ besser ist und schneller reift als eine Neuentwicklung. So zeigen Basili, Briand und Melo (1996a) in einer Studie, dass die Fehlerdichte in wiederverwendeten Komponenten deutlich geringer ist als in neu entwickelten Komponenten.
In der Literatur finden sich viele recht komplexe Antworten auf die Frage, wann sich Wiederverwendung lohnt (siehe z. B. Favaro, Favaro, Favaro, 1998 oder Mili et al., 2001). Wir verwenden das folgende einfache Modell für die Berechnung der Kosten und des Nutzens durch Wiederverwendung:
K = KEV + ∑ iKA und N = ∑ i(NE + NQ)
Dabei sind K die Gesamtkosten, die sich aus den Entwicklungs- und Verwaltungskosten (KEV) sowie aus den jeweiligen Anpassungskosten (KA) bei der Wiederverwendung ergeben. Natürlich handelt es sich hier stets um die erwarteten (also geschätzten, der Planung zu Grunde gelegten) Entwicklungskosten. Der Nutzen N ist die Summe aus gesparten Entwicklungskosten (NE) und dem Nutzen, der durch die höhere Qualität entsteht (NQ).
Um zu bestimmen, wann sich die Wiederverwendung lohnt, gehen wir von folgenden Annahmen aus:
Um eine wiederverwendbare Software-Einheit zu entwickeln und zu verwalten, wird im Mittel 80 % Mehraufwand benötigt.
Die Kosten, eine wiederverwendbare Software-Einheit zu finden und dem speziellen Einsatz anzupassen, betragen im Mittel 20 % der Entwicklungskosten.
Der Nutzen durch höhere Qualität entspricht 10 % der Entwicklungskosten.
Setzen wir diese Werte, bezogen auf die Entwicklungskosten x, in die Formeln oben ein, ergeben sich für n Verwendungen der Software folgende Werte:
K = 1,8x + ∑ i0,2x = (1, 8 + n · 0, 2) · x |
N = ∑ i(x + 0,1x) = 1, 1 · n · x |
Barnes und Bollinger (1991) stellen die naheliegende Forderung, dass der Nutzen die Kosten übersteigt: K < N, d. h. 1,8 + 0,2 n < 1,1 n oder n > 2. Bei zwei Verwendungen halten sich also, wenn die Annahmen zutreffen, Kosten und Nutzen mit 2,2 x die Waage, bei drei Verwendungen überwiegt der Nutzen.
Die Rechnung zeigt, dass sich die Entwicklung wiederverwendbarer Software schon bei wenigen Einsätzen rentiert. Sie stellt dennoch eine beträchtliche Investition dar. Darum kommt es bei einem Software-Hersteller, der ohne langfristige Planung agiert, also quasi von der Hand in den Mund lebt, kaum zur Wiederverwendung.
Die Wiederverwendung von Software-Einheiten kann sich günstig auswirken. Folgende Vorteile können erzielt werden:
Die Entwicklungskosten sinken und die Entwicklungszeit wird verkürzt, weil Entwicklungsarbeit eingespart wird.
Die Kosten für eine Software-Entwicklung lassen sich beim Einsatz bereits entwickelter Teile präziser vorhersagen, weil die Kosten für Anpassung und Integration genauer geschätzt werden können als für eine komplette Entwicklung.
Die entwickelte Software ist besser, weil ausgereifte Software-Einheiten eingesetzt werden.
Verwandte Systeme können leichter gewartet werden, weil die Korrektur einer mehrfach verwendeten Software-Einheit viele Systeme verbessert.
Die restlichen Fehler fallen schneller auf, weil eine mehrfach eingesetzte Software-Einheit viele Benutzer hat. Dadurch reift sie schneller.
Es gibt also viele Gründe, die Wiederverwendung zu fördern. Allerdings gibt es auch eine Reihe von Hindernissen.
Wiederverwendung setzt vor allem Stabilität der Software voraus. Ist die Software aus irgendeinem Grunde nicht stabil, so sollte nicht zu viel in die Wiederverwendung investiert werden. Beispielsweise hat es in der Forschung oft keinen Sinn, die Software auf lange Lebensdauer und Wiederverwendung auszulegen, weil sie schon nach wenigen Monaten überholt ist.
Dieses Problem lässt sich anhand der Programmklassen nach Lehman (Abschnitt 9.3) klarer beschreiben. Offensichtlich sind die Programme der S-Klasse sehr gut zur Wiederverwendung geeignet, weil ihre Spezifikation stabil bleibt. Wenn sie einmal entwickelt sind, können sie problemlos wiederverwendet werden. Es besteht kein Risiko, dass sie und damit auch die Anwendungen, die darauf aufbauen, angepasst werden müssen. Tatsächlich haben wir heute in diesem Bereich durch Produkte und Programm-Bibliotheken einen hohen Grad an Wiederverwendung erreicht.
Software der P-Klasse ist so stabil wie die zu Grunde liegenden Modelle der realen Welt; sie können als Lösungspakete wiederverwendet werden; möglicherweise können einzelne ihrer Komponenten als S-Programme isoliert und wiederverwendet werden.
Software der E-Klasse ist niemals stabil, weil sich ihre Voraussetzungen und damit die Anforderungen durch ihre Existenz ändern. Um bei solchen Systemen Wiederverwendung zu erreichen, muss entweder die Rückkopplung gekappt werden (das geschieht praktisch bei Produkten), oder die Benutzer erhalten die Möglichkeit, selbst das System zu ändern (d. h., die Evolution findet teilweise unter der Kontrolle der Benutzer statt).
Ob wiederverwendbare Software-Komponenten entstehen können und auch wiederverwendet werden, hängt von den Rahmenbedingungen der Software-Entwicklung ab. In Tabelle 24–1 sind günstige und ungünstige Bedingungen für die Wiederverwendung zusammengestellt.
|
ungünstiges Szenario |
günstiges Szenario |
Die Projekte sind |
sehr unterschiedlich |
einander ähnlich |
Notationen und Sprachen |
sind in großer Vielfalt im Einsatz |
gibt es jeweils nur eine für einen Zweck |
Zwischen den Projekten gibt es |
kaum Kontakt, Projekte sind sehr selbstständig |
starke Verbindungen, z. B. durch Qualitätszirkel, Personalaustausch, Reviews |
Die Entwickler sind |
typische Künstler |
typische Ingenieure |
Das Management ist |
schwach, passiv |
stark, kompetent, führend |
Der Termindruck ist |
dauernd sehr hoch |
nur ausnahmsweise hoch, meist erträglich |
Die Qualitätssicherung ist |
nicht vorhanden oder schwach |
projektunabhängig, etabliert und anerkannt |
Das Erfolgskriterium der Entwickler und Manager ist |
einzig die termingerechte Auslieferung |
neben der Planeinhaltung die erzielte Wiederverwendung und der Umfang neu entstandener wiederverwendbarer Einheiten |
Tab. 24–1 Rahmenbedingungen der Wiederverwendung
Wenn man Fortschritte in Richtung auf eine geplante Wiederverwendung machen will, sollte man einige Faktoren beachten, die in der Praxis erheblichen Einfluss haben. Die nachfolgende Liste ist natürlich bei weitem nicht vollständig.
Wiederverwendung muss belohnt werden!
Niemand entwickelt unmotiviert wiederverwendbare Software, denn das bedeutet Mehraufwand. Das gilt erstaunlicherweise auch für das Verwenden der Komponenten. Auf den ersten Blick erscheint es oft einfacher, eine Komponente neu zu entwickeln, als eine vorhandene Komponente anzupassen. Wenn Wiederverwendung stattfinden soll, dann müssen sowohl für die Geber als auch für die Nehmer Anreize geschaffen werden.
Der Nutzen der Wiederverwendung muss durch Metriken belegt werden!
Bei allen Aspekten der Software-Entwicklung ist es wichtig, dass wir die Ergebnisse unserer Anstrengungen wenn möglich quantitativ belegen können. Das gilt auch für die Wiederverwendung. Deshalb ist es notwendig, dass zentrale Aspekte der Wiederverwendung gemessen werden können. Dazu zählen insbesondere die Betrachtung der Kosten und des Nutzens, aber auch die Feststellung, in welchem Umfang die Wiederverwendung genutzt wird. Frakes und Terry (1996) geben einen Überblick und eine Klassifikation der Metriken an, die im Kontext der Wiederverwendung angewendet werden können.
Die Qualitätssicherung muss die Wiederverwendung unterstützen!
Wiederverwendbare Software-Komponenten müssen höheren Qualitätsanforderungen genügen als andere Software (z. B. bezüglich ihrer Robustheit). Deshalb müssen sie sehr systematisch und intensiv geprüft werden. Eine wiederverwendete Komponente muss natürlich auch im Kontext der umgebenden Anwendung geprüft werden. Dabei sollten die einmal erstellten Testfälle wiederverwendet werden können. Sie müssen entsprechend gestaltet und verwaltet werden. In Kolb, McGregor und Muthig (2004) sind einige Beiträge zu finden, die Ansätze für eine wiederverwendungsorientierte Qualitätssicherung skizzieren.
Standards und Richtlinien müssen definiert und eingehalten werden!
Je kleiner die Variationsbreite im Bereich der eingesetzten Programmiersprachen, Werkzeuge und Entwicklungstechnologie in einem Unternehmen ist, desto leichter und häufiger können Einheiten wiederverwendet werden, weil die Standardisierung die Kompatibilität fördert.
Bibliotheken von Standardkomponenten müssen zur Verfügung stehen und auch genutzt werden!
Für die gängigen Programmiersprachen stehen viele Bibliotheken mit Standardkomponenten zur Verfügung, werden aber bei weitem nicht überall genutzt. Beispielsweise werden Datenstruktur-Komponenten noch neu entwickelt. Dies ist weder sinnvoll noch wirtschaftlich. Es genügt nicht, die Bibliotheken einzukaufen und bereitzustellen; organisatorische Maßnahmen müssen sicherstellen, dass diese Bibliotheken auch in den Entwicklungsprojekten genutzt werden.
Seit Beginn der Informatik sind viele Programmierkonzepte und Entwicklungstechniken entstanden, die die Wiederverwendung erleichtern oder unterstützen (Abb. 24–4).
Abb. 24–4 Entwicklungstechniken der Wiederverwendung
Wenn wir eine Befehlssequenz zu einer benannten Prozedur zusammenfassen, brauchen wir die konkrete Implementierung nicht mehr zu betrachten. Jeder Prozeduraufruf dient der Wiederverwendung, wobei die Anpassung durch die Prozedurparameter erfolgt.
Die Sprache MODULA stellte dem Programmierer erstmals ein Modulkonzept mit klarer Trennung von Schnittstelle und Implementierung zur Verfügung. Die Module fördern die Implementierung gekapselter Datenstrukturen und Abstrakter Datentypen; durch die Abstraktion von der Realisierung der Datentypen wird die Wiederverwendung leichter und sicherer, als es ohne Information Hiding (siehe Abschnitt 17.3.3) möglich war.
Die objektorientierte Programmierung wurde (und wird gelegentlich auch heute noch) als Allheilmittel der Wiederverwendung dargestellt, weil Klassen mit Hilfe der Vererbung flexibel abgeleitet und wiederverwendet werden können (siehe Abschnitt 17.4.1). Dabei wird allerdings gern ignoriert, dass Klassen in einer Klassenhierarchie sehr eng gekoppelt sind und darum einzeln kaum wiederverwendet werden können.
Wenn Anwendungsbereiche gut verstanden sind (z. B. Informationssysteme, Übersetzer), kann das Wissen über die Funktionsweise und den Aufbau dieser Anwendungsbereiche in einem Programmgenerator abgelegt werden. Der Entwickler kann die zu erstellende Anwendung auf hohem Abstraktionsniveau beschreiben, je nach Generator auch visuell oder mit Hilfe einer 4th-Generation Language (4GL, Martin, 1982). Der Programmgenerator erzeugt aus der Beschreibung den Code der Anwendung; der Grad der Wiederverwendung ist entsprechend hoch. Beispiele für Programmgeneratoren sind 4G-Systeme (4th-Generation Systems), mit denen Datenbank-Anwendungen erzeugt werden können, Parser-Generatoren wie lex und yacc und Bedienoberflächen-Generatoren, die heute in vielen integrierten Entwicklungsumgebungen enthalten sind. Biggerstaff (1998) beschreibt diesen Ansatz im Detail.
Rahmenwerke geben die Architektur für alle darauf aufbauenden Anwendungen vor und implementieren die Teile, die allen Anwendungen gemeinsam sind (siehe Abschnitt 17.5.3). Beim Einsatz von Rahmenwerken wird neben den Code-Komponenten auch die Architektur wiederverwendet.
Muster helfen, allgemeine oder spezielle Anforderungen in einer Software zu erfüllen. Besonders im Bereich des Software-Entwurfs kennen wir Muster auf der Ebene der Architektur (siehe Abschnitt 17.5.1) und Muster auf der Ebene des detaillierten Entwurfs (siehe Abschnitt 17.5.2). Muster haben dazu beigetragen, dass nicht nur Code-Komponenten Gegenstand der Wiederverwendung sind.
Die komponentenbasierte Programmierung ist angetreten, um die Schwächen der Objektorientierung in Bezug auf die Wiederverwendung zu überwinden, indem in sich abgeschlossene wiederverwendbare Einheiten, die Komponenten, entwickelt werden. Praktisch sind die Komponenten immer auf ein Komponentenmodell (z. B. EJB, CORBA 3 oder .NET) zugeschnitten und dann auch nur innerhalb des Komponentenmodells verwendbar. Die hohen Erwartungen an die komponentenbasierte Entwicklung wurden jedoch nicht erfüllt.
Die Entwicklung von Produktlinien ist in vielen Bereichen (z. B. in der Telekommunikationsindustrie) eine bewährte Vorgehensweise, um eine Menge ähnlicher Produkte herzustellen und dabei eine große gemeinsame Basis an wiederverwendbaren Produktbestandteilen zu pflegen. Diese Idee hat David Parnas schon früh vorgestellt und den Begriff »program family« eingeführt und geprägt (Parnas, 1976). Aber erst Ende der Neunzigerjahre wurde diese Art der Software-Entwicklung systematisch erforscht und umgesetzt (Clements, Northrop, 2001; Pohl, Böckle, van der Linden, 2005). Dabei werden zwei Bereiche unterschieden: Im Domain Engineering werden die wiederverwendbaren Produktbestandteile identifiziert und entwickelt, im Application Engineering werden sie für die Konstruktion von Produkten genutzt.
Bei der modellgetriebenen Software-Entwicklung werden die fachlichen Anforderungen in Modellen spezifiziert, die von der Zieltechnologie unabhängig sind (siehe Abschnitt 15.4). Die Modelle werden durch spezielle Werkzeuge auf Implementierungsmodelle abgebildet, die die speziellen Bedingungen der Technologie (z. B. CORBA, J2EE, .NET) berücksichtigen. Der Schwerpunkt der Wiederverwendung liegt auf den Modellen und den Modelltransformationen.
Die Idee, bei der Software-Entwicklung nicht immer alle Teile neu zu erfinden und zu entwickeln, sondern vorhandene Software-Einheiten wiederzuverwenden, ist so alt wie das Software Engineering selbst. Bereits 1968 hielt Douglas McIlroy auf der Garmischer NATO-Konferenz einen Vortrag2 zum Thema »Mass produced software components« und beschrieb die Idee der Wiederverwendung durch Komponenten sehr treffend:
My thesis is that the software industry is weakly founded, and that one aspect of this weakness is the absence of a software components subindustry. ... The most important characteristic of a software components industry is that it will offer families of routines for any given job. No user of a particular member of a family should pay a penalty, in unwanted generality, for the fact that he is employing a standard model routine. In other words, the purchaser of a component from a family will choose one tailored to his exact needs. He will consult a catalogue offering routines in varying degrees of precision, robustness, time-space performance, and generality. He will be confident that each routine in the family is of high quality – reliable and efficient. He will expect the routine to be intelligible, doubtless expressed in a higher level language appropriate to the purpose of the component, though not necessarily instantly compilable in any processor he has for his machine. He will expect families of routines to be constructed on rational principles so that families fit together as building blocks. In short, he should be able safely to regard components as black boxes.
M.D. McIlroy (1969)
Um zu begreifen, wie visionär die Ideen von McIlroy waren, muss man sich die Situation der Software-Entwickler gegen Ende der Sechzigerjahre klar machen:
Es gab nur sehr große, sehr teure Rechner, die untereinander inkompatibel waren, wenn sie nicht zur selben Baureihe gehörten.
Alle Betriebssysteme waren proprietär.
Die einzige Möglichkeit, Software auf einen anderen Rechner zu bringen, bestand darin, einen Kasten mit Lochkarten oder eine schwere Magnetbandspule herumzutragen oder zu verschicken.
Heute haben wir vor allem dank Linux und Windows auf den Arbeitsplatzrechnern ausgezeichnete Kompatibilität und weitgehende Unabhängigkeit von den Hardware-Herstellern, dazu ein Internet, das es uns erlaubt, Software in wenigen Sekunden um die halbe Welt zu transportieren. Tatsächlich ist damit der Austausch von Software zur täglichen Routine geworden.
Trotzdem sind wir noch immer weit davon entfernt, Software so zu entwickeln, wie es die Metapher des Software-ICs (Cox, 1986) in Aussicht stellte. Integrierte Schaltungen (ICs) werden im Katalog ausgesucht und auf Platinen gesteckt oder gelötet. Wer ein spezielles Gerät entwickeln will, kann aus einem großen Angebot wählen und braucht selbst keine Komponenten zu entwickeln. Was fehlt uns, um so zu arbeiten?
ICs haben eine präzise Spezifikation, die sie generell einhalten.
ICs haben konzeptionell einfache, standardisierte Schnittstellen.
ICs sind ausreichend universell, um für viele Anwendungen brauchbar zu sein.
ICs lassen sich durch Firmware und Software spezialisieren.
ICs sind zuverlässig und um Größenordnungen billiger als jede Eigenentwicklung.
Wenn es uns gelingt, Software-Bausteine bereitzustellen, die diese Merkmale der ICs aufweisen, werden wir in der Lage sein, Systeme zu entwickeln, indem wir verfügbare Komponenten auswählen, entsprechend unseren Anforderungen ausprägen und integrieren. Die Codierung neuer Komponenten bleibt einer kleinen Gruppe von Entwicklern vorbehalten. Gewöhnliche Programmierer codieren ihre Programme nicht mehr, sondern komponieren sie aus Komponenten. Sie erreichen dadurch hohe Qualität, kurze Entwicklungsdauer, geringe Zahl unterschiedlicher Komponenten und geringe Kosten. So stellen wir uns die Software-Baustellen der Zukunft vor!