Ohne Re-Engineering keine dauerhafte Qualitaet Korrektur muss schon bei der Software-Entwicklung greifen

17.12.1993

Re-Engineering gilt manchen Kennern als ein teurer, oft wenig wirkungsvoller Versuch, Programmierfehler nachtraeglich zu beheben. Nach Auffassung von Juergen Schmitz* muessen Re-Engineering- Verfahren dagegen bereits Teil der Software-Entwicklung selbst sein. Er erlaeutert seine These insbesondere am Beispiel der Dokumentation.

Re-Engineering und Qualitaet ist ein selten gesehenes Begriffspaar. Wenn es um das Thema Qualitaet bei der Software-Entwicklung geht, liegt der Fokus meist auf Methoden, Verfahren und Tools. Qualitaet entsteht bei der Entwicklung, und Versaeumtes kann nicht nachtraeglich in ein System hineingezwungen werden. Re-Engineering steht eher in dem Ruf, der letzte Therapieversuch zu sein, bevor ein Softwaresystem an chronischer Unwartbarkeit dahinscheidet.

Der folgende Beitrag begreift Re-Engineering nicht als Einzelmassnahme zur Softwaresanierung, sondern als notwendigen Bestandteil eines auf Qualitaet abzielenden Vorgehensmodells fuer Software-Entwicklung. Ohne Re-Engineering keine dauerhafte Qualitaet! Der Begriff "Qualitaet" hat zahlreiche Facetten. Zuverlaessigkeit, Robustheit, Wartbarkeit etc. sind Beispiele dafuer. Eine Grundvoraussetzung fuer die Erreichung und dauerhafte Sicherung dieser Qualitaetsziele ist die entwicklungsbegleitende, aktuelle Dokumentation. Ohne diese ist der Bemuehung um Qualitaet jegliche Grundlage entzogen.

Eine auf die Dauer aktuelle Dokumentation

Das folgende Beispiel soll zeigen, dass Re-Engineering-Techniken einen unverzichtbaren Beitrag zur Gewaehrleistung einer auf Dauer aktuellen Dokumentation darstellen. Der Begriff "Dokumentation" soll dabei als Platzhalter fuer die unterschiedlichen Formen von Entwicklungsdokumenten wie Pflichtenheft, Systemdokumentation, Programmdokumentation etc. stehen.

Das Szenario: Fuer eine hochmoderne, weitgehend durch Computer gesteuerte Produktionsanlage (zum Beispiel ein Walzwerk) ist die Betriebssoftware fuer die Prozesssteuerung und Regelung der Maschinen in einer Unix-Entwicklungsumgebung nach allen Regeln der Qualitaetskunst realisiert worden. Die Dokumentation haben die Entwickler unter anderem mit CASE-Tools in Verbindung mit Desktop- Publishing-Systemen nach den firmenspezifischen Standards erstellt. Waehrend der Inbetriebnahme werden Softwarefehler entdeckt und sind zu korrigieren. Aber auf der Baustelle gibt es keine Software-Entwicklungsumgebung. Die Zielhardware besteht aus intelligenten Controllern auf Mikroprozessorbasis und aus Prozessrechnern. Fuer die Software-Entwicklung stehen allenfalls Editor, Compiler, Linker und Debugger zur Verfuegung. Aus Kostengruenden muss jeder Softwarefehler sofort und mit den auf der Baustelle zur Verfuegung stehenden Mitteln korrigiert werden. Es handelt sich nicht nur um Programmier-, sondern moeglicherweise auch um Designfehler. Auch letztere sind auf Sourcecode-Ebene im Programm zu korrigieren, mit gravierenden Konsequenzen fuer die Software-Architektur. Wie kann noch an diesen Aenderungen die Konsistenz zwischen Dokumentation und Programmcode sichergestellt werden? In dieser Situation gibt es nur eine Loesung: Ein Re- Engineering der Analyse- und Designdokumentation, ausgehend vom juengsten, auf der Baustelle gueltigen Sourcecode-Stand.

Diese Situation ist kein pathologischer Einzelfall, sondern laesst sich auf eine breite Klasse von Anwendungsbereichen verallgemeinern.

Zur Begruendung ist es erforderlich, sich anhand eines Phasenmodells der Software-Entwicklung vor Augen zu halten, in welchen Schritten Dokumentation entsteht. Grob vereinfacht differenzieren wir hier nur zwischen den Phasen der Analyse, des Designs und der Implementierung. Unabhaengig von der Wahl des Phasenmodells (sequentiell, in Spiralen, evolutionaer etc.) und der Entwicklungsmethodik (klassisch strukturiert, objektorientiert, 4GL etc.) laesst sich der Prozess der Software-Entwicklung auf die schlichte Formel reduzieren, ausgehend von einer groben, informellen und unvollstaendigen Idee ein Endprodukt ableiten zu muessen, das detailliert, streng formal und vollstaendig ist. Letzteres ist die Charakterisierung eines ablauffaehigen Programms beziehungsweise seiner Grundlage, des Sourcecodes.

Software-Entwicklung ist also ein Prozess zunehmender Informationsgewinnung und Formalisierung. Bei jedem Schritt zwischen Analyse, Design und Implementierung fuege ich "Wissen" ueber mein System hinzu (vgl. die Abbildung). In der Analyse beschreibe ich die Anwendungsfunktionen des geplanten Systems. Im Design werden die anwendungsbezogenen Funktionen um DV-technische Funktionen ergaenzt. Im Programm kommt zu jeder Funktion die algorithmische Realisierung auf Basis der elementaren Rechneroperationen hinzu. Wenn beispielsweise im Pflichtenheft die anwendungsbezogene Funktion "Drucke Bericht" beschrieben ist, so wird das Design nicht nur diese Druckfunktion enthalten, sondern zusaetzlich noch Funktionen zur physischen Ansteuerung des Druckers (Druckertreiber) beruecksichtigen muessen. Da den Anwender herzlich wenig interessiert, wie die Software den Bericht auf den Drucker bekommt, hat der Druckertreiber im Pflichtenheft nichts zu suchen, sondern ist echtes "Zusatzwissen" im Design. Das "Wissensgefaelle" zwischen den Phasen fuehrt zu der Situation, dass bei der Softwarewartung die Dokumentation nicht durch eine reine Vorwaertsstrategie konsistent gehalten werden kann. Denn bei einer Aenderung in einem bestimmten Abschnitt der Programmentwicklung sind die Auswirkungen auf die naechste Phase nicht direkt ableitbar. Beispiel: Im Druckertreiber fehlt eine Funktion zur Ausgabe einer Fehlermeldung an den Benutzer. In der Designdokumentation ist die Auswirkung minimal, es wird eine entsprechende Funktion hinzugefuegt. Diese Designaenderung laesst sich nun nicht eins zu eins auf den Sourcecode uebertragen, denn es ist nicht abzusehen, in welchen Programmanweisungen und wie oft die neue Funktion genutzt wird.

Um sicher zu sein, dass nach der Sourcecode-Aenderung die Designdokumentation noch stimmt, wird der Software-Entwickler rueckwaerts Sourcecode und Designdokumentation vergleichen und letztere gegebenenfalls anpassen. Das ist offensichtlich mit Doppelarbeit verbunden. Warum erst die Designdokumentation aktualisieren, um sie spaeter ein zweites Mal anzupacken? Die Konsequenz: Auf die Initialaenderung im Design wird moeglicherweise ganz verzichtet, und ueber die Qualitaet der Dokumentation entscheiden Re-Engineering-Techniken.

Auch Verfahren und Werkzeuge, die mit einer Generierung arbeiten, schwaechen diese Argumentation nicht. Wenn ich ein Werkzeug einsetze, das einwandfreien Code generiert, dann habe ich den Formalisierungsschritt nicht gespart, sondern auf eine andere Darstellungsebene, zum Beispiel die des Pseudo- codes, verlagert.

Nur Techniken, die das Programm direkt aus der Spezifikation ableiten koennen, bilden eine Ausnahme. In diesem Fall gibt es offensichtlich kein Konsistenzproblem zwischen Dokumentation und Programm, und Re-Engineering-Verfahren sind ueberfluessig. Vertreter dieser Techniken sind mathematische Spezifikationsmethoden. Weitere Beispiele lassen sich in sehr eingeschraenkten Anwendungsbereichen finden. Kalkulationsprogramme gehoeren dazu, weil die Spezifikation einer Aufgabe als matrixfoermiges Rechenschema mit dem Programm zur Loesung uebereinstimmt.

Welchen Einfluss hat der Werkzeugeinsatz auf die Pflege der Dokumentation? Kann durch CASE-Werkzeuge auf Re-Engineering in der Softwarepflege verzichtet werden? Zunaechst scheint es so, denn CASE-Tools betonen das Forward Engi- neering. Zudem ist aus technologischer Sicht der Vorwaertsweg wesentlich einfacher zu automatisieren. Das liegt daran, dass Re-Engineering einen Abstraktionsprozess beinhaltet. Um aus dem Sourcecode Rueckschluesse auf das Design zu ziehen, ist eine Abstraktion von den programmtechnischen Details und Konzentration auf die globalen Programmzusammenhaenge erforderlich. Um aus einem Design ein Analysedokument ableiten zu koennen, ist es notwendig, die Anwendungsfunktionen aus der Menge der im Design dokumentierten Funktionen herauszufiltern. Gerade letzteres scheint bis auf weiteres nicht automatisierbar zu sein. Wie sollte ein Programm erkennen, dass ein Druckertreiber eine DV-technische Funktion ist, die nicht ins Pflichtenheft gehoert?

Trotzdem bleibt das Re-Engineering fuer die Softwarepflege unverzichtbar. Bei der Erstentwicklung lassen sich Phasengrenzen erfolgreich durch Generierungstechniken ueberwinden, aber in der Pflege wiederholt sich das oben bereits bezeichnete Dilemma: Eine Designaenderung kann nicht automatisch in existierenden Code integriert werden.

Der Abstraktionsprozess fuer den Rueckwaertsgang

Erstaunlicherweise laesst sich der zunaechst als viel schwieriger erscheinende Abstraktionsprozess fuer den Rueckwaertsweg realisieren. Die Unterscheidung zwischen programmtechnischen Details und fuer das Systemverstaendnis relevanten Designinformationen faellt leicht: Alle Programmelemente mit nur lokaler Bedeutung (zum Beispiel Schleifenzaehler) werden ignoriert, die globalen Elemente wie Schnittstellen extrahiert und dokumentiert. Diese Unterscheidung kann durch den Einsatz von Compiler-Technologie automatisiert werden. Es gibt inzwischen eine Vielzahl von Werkzeugen, die eine Designabstraktion aus Code unterstuetzen. Dabei handelt es sich in der Regel um Komponenten von CASE-Tools oder von Programmierumgebungen (Sourcecode-Browser).

Ein weiterer Schritt zurueck im Life-Cycle ist allerdings nicht mehr moeglich, da fuer die Abstraktion zwischen Design und Analysemodell die Heuristiken fehlen. Hier kann sich ein Werkzeug aber immerhin "merken", wie die Elemente zwischen Analyse und Design voneinander abhaengen, und den Bereich des Analysemodells, der durch eine Designaenderung betroffen ist, identifizieren. Auch der Blick auf die Werkzeuglandschaft bestaetigt also die Bedeutung des Re-Engineerings fuer eine dauerhafte Konsistenz zwischen Dokumentation und Programm. Auf dem Markt gibt es einen regelrechten Boom an Re-Engineering-Tools. Wer Leistungen anbieten kann, die Qualitaet nicht nur bei der Neuentwicklung, sondern auch in der nachfolgenden Pflege sichert, verschafft sich einen Wettbewerbsvorteil und erschliesst einen neuen Kundenkreis bei Firmen, die ihre Entwicklungsressourcen ueberwiegend fuer die Softwarepflege aufwenden.