Software-Werkzeuge der strukturierten Programmierung, Teil II\

Entwicklungshilfen auch für DV-Manager

25.09.1981

3. Generierung von Struktogrammen

Um die Lesbarkeit von Programmen zu erhöhen, wurden verschiedene Methoden entwickelt, die von einer linearen Aufschreibung wegführen, da sie den zugrunde liegenden Algorithmen nicht entspricht. Neben Flußdiagrammen, die noch zu sehr von der verwendeten Programmiersprache abhängen, sind wohl die von Nassi und Shneiderman entwickelten Struktogramme am bekanntesten. Ihr Anwendungsgebiet reicht von der Entwurfs- bis zur Testphase, und natürlich dienen sie zur Dokumentation.

Bei dieser Methode werden bestimmte Strukturwörter aus dem Programmtext herangezogen, um ein zweidimensionales Bild entstehen zu lassen, aus dem der Kontrollfluß direkt abgelesen werden kann. Blöcke werden dabei umrahmt, Alternativen bei Verzweigungen nebeneinandergestellt. Stellen, an denen ein Block vor seinem statischen Ende verlassen werden kann (zum Beispiel bei Schleifen) oder an denen eine Prozedur aufgerufen wird, werden gekennzeichnet.

Da dieses Verfahren unabhängig von der den Programmen zugrunde liegenden Sprache ist, ist es sehr vielseitig einsetzbar. Ein Struktogramm-Generator löst dabei ein Problem auf elegante Weise, das der Einführung der strukturierten Programmierung in Produktionsumgebungen bisher im Wege stand: der hohe Aufwand bei der manuellen Erstellung von Ablaufplänen, vor allem bei der Einteilung in Spalten und Blöcke, und bei ihrer Änderung. Die Zeichenarbeit, die die Nassi-Shneiderman-Methode sonst vom Software-Entwickler verlangt, wird bei Einsatz eines Struktogramm-Generators vom Rechner geleistet.

Sinnvollerweise sollte man bei der automatischen Erstellung dieser Diagramme gewisse Parameter einstellen können wie die Seitenbreite, eine Mindestbreite für die einzelnen Strukturblöcke oder die Angabe, ob beim Zeilenumbruch Silbentrennung durchgeführt werden soll. Bei komplexeren Strukturen ist es im System Sindus möglich, mehrere Papierbahnen nebeneinanderzulegen und so ein vollständiges Bild zu erhalten.

4. Strukturierte Programmierung in gängigen Programmiersprachen

4.1 Allgemeine Prinzipien

Gerade die am häufigsten verwendeten Programmiersprachen, neben den Assembler-Sprachen also Cobol und Fortran, unterstützen die strukturierte Programmierung nur in sehr eingeschränktem Umfang. Dafür besser geeignete Sprachen wie etwa Pascal lassen sich aber anscheinend noch nicht durchsetzen. Um es dem Programmierer zu ermöglichen, wohlstrukturierte Programme zu schreiben, ohne lange umlernen zu müssen lag es daher nahe, Vorübersetzer zu entwickeln. Sie erzeugen aus einem mit Schlüsselworten der strukturierten Programmierung versehenen Text ein der Syntax und den Konventionen der verwendeten Programmiersprache entsprechendes Programm.

Da die bereits beschriebenen Konstruktionen ausreichen, um beliebige Kontrollflüsse zu beschreiben (vgl. D. Harel, CACM 23 (1980), S. 379-389), sollten neben diesen Strukturanweisungen keine Anweisungen aus der Programmiersprache verwendet werden, die den Kontrollfluß beeinflussen. Davon abgesehen bestehen jedoch keine Einschränkungen für den Programmierer. Im Gegenteil können die Vorübersetzer den Anwender sogar weitgehend von den sehr aufwendigen Formatierungsvorschriften der verschiedenen Sprachen befreien, wobei sie auch Fortsetzungszeilen automatisch generieren und Kommentare einheitlich behandeln. Durch die Verwendung von einheitlichen Schlüsselworten sowohl für die verschiedenen Vorübersetzer als auch für den Struktogramm-Generator wird die Anwendung dieser Methode im System Sindus noch weiter vereinfacht.

Es versteht sich von selbst, daß die von Vorübersetzern erzeugten Anweisungen effizient sein müssen. Insbesondere die Anzahl von Sprungbefehlen ist zu minimieren, indem beispielsweise Sprungbedingungen in bestimmten Fällen negiert werden. Es kann verhindert werden, mehrere Marken auf dieselbe Programmstelle zu generieren. Dadurch erübrigen sich Leerbefehle (NOP in Assembler, CONTINUE in Fortran) fast vollständig. Zwar etwas aufwendig, aber durchaus wünschenswert ist es, Sprungketten zu erkennen und durch einen direkten Sprung an das letzte Ziel der Kette zu ersetzen.

Wie der Name Vorübersetzer schon sagt, soll jedoch noch keine Syntaxprüfung des Programmtextes vorgenommen werden. Das bleibt einem nachfolgenden Übersetzungslauf vorbehalten. In den folgenden Abschnitten werden einige Eigenschaften von Vorübersetzern für gängige Programmiersprachen an Hand von Beispielen beschrieben.

4.2 Vorübersetzer für Assembler

Zur Demonstration wird hier der auf IBM- und Siemens-Anlagen verwendete Assembler herangezogen. Das Beispiel zeigt, daß der Vorübersetzer dem Programmierer auch viel Schreibarbeit erspart.

Durch die im folgenden aufgeführten Strukturanweisungen wird die Verwendung von Prozeduren in der Assembler-Sprache möglich.

Folgende Eigenschaften kennzeichnen eine Prozedur:

- Sie kann von einer beliebigen Stelle aus mittels einer CALL-Anweisung aufgerufen werden. Nach Ausführung der Prozedur kehrt die Steuerung an die der Aufrufanweisung folgende Anweisung zurück.

- Sie kann nur an ihrem statischen Kopf (ENTER) betreten werden.

- Der Steuerfluß kann von jeder beliebigen Stelle der Prozedur aus zum Aufrufer zurückkehren (EXIT: dynamisches Prozedurende).

Erzeugte Prozedurköpfe, Rücksprung- und Aufrufanweisungen entsprechen den jeweiligen Systemkonventionen. Damit ist Aufrufbarkeit von anderen Programmiersprachen gewährleistet.

Beispiel: Codegenerierung für eine externe Prozedur mit Registersicherung, die Startprozedur eines Moduls ist. Die Registersicherung entspricht IBM-Konventionen.

Ein weiteres Beispiel zeigt, wie mit Hilfe von Strukturanweisungen und Verknüpfungsanweisungen Bedingungen formuliert werden können:

4.3 Vorübersetzer für Cobol

Dem Anwender wird die Einteilung des Programms in Kapitel, Paragraphen und Sätze abgenommen. Das Konzept der Einteilung des Prozedurteils eines Cobol-Programms in Kapitel und Paragraphen wird zur Erzeugung des Zielcodes in einer der strukturierten Programmierung gemäßen Weise eingesetzt: Aus internen Prozeduren eines Programms werden Kapitel, aus Strukturblöcken, sofern sie auch von einer anderen Stelle als der unmittelbar vorhergehenden Anweisung aus betreten werden können, werden Paragraphen.

Punkte zum Abschließen von Cobol-Sätzen können im Quelltext beliebig verwendet werden, sind jedoch nicht notwendig. Sie werden im Zielcode eingefügt, wo sie erforderlich sind.

Beispiel: Schleife mit Durchlaufanweisung.

4.4 Vorübersetzer für Fortran

Neben den in Fortran üblichen Programmeinheiten stellt der hier beschriebene Vorübersetzer noch die Konstruktion einer parameterlosen internen Prozedur zur Verfügung, die innerhalb eines Moduls von verschiedenen Stellen aus aufgerufen werden kann. Eine Variable vom Typ INTEGER mit dem Prozedurnamen als Identifikator ist dafür zu deklarieren.

Beispiel: Codegenerierung für eine interne Prozedur.

4.5 Vorübersetzer für PL/1

Der Programmtext wird in einem aufbereiteten Format in die Ausgabedatei geschrieben. Die in generierten DO-Gruppen stehenden ausführbaren Anweisungen werden jeweils um zwei Stellen eingerückt, dazugehörige Fortsetzungszeilen um weitere zwei Stellen.

Beispiel: Fallunterscheidung.

Hinter CASE steht ein Ausdruck, der in PL/1 als Index (Subscript) zulässig ist. Die Sprungtabelle S0002 enthält so viele Marken, wie Fälle aufgeführt sind. Sie wird unmittelbar hinter dem Prozedurknopf generiert.