| Dieser Artikel oder Abschnitt bedarf einer Überarbeitung. Näheres ist auf der Diskussionsseite angegeben. Hilf mit, ihn zu verbessern, und entferne anschließend diese Markierung. |
Die normierte Programmierung beschreibt den Versuch einer standardisierten Ablaufsteuerung eines Datenverarbeitungsprogramms. Sie war in DIN 66220 genormt und wurde mit DIN 66260 in Richtung strukturierte Programmierung weiterentwickelt. Beide Ansätze unterstützten die modulare Programmierung.
Normierte Programmierung ist eine verallgemeinerte Programmablaufsteuerung, die die Teilaufgaben eines Stapelprogrammes wie Dateneingabe, Gruppenkontrolle, Verarbeitung, Ausgabe in ein einheitliches, logisch klares, funktionelles Schema gliedert. Dieses Schema lässt sich unabhängig von der Aufgabenstellung und unabhängig von der Programmiersprache für alle kommerziellen Computerprogramme anwenden.
Laut einem kleinen Lehrbuch eines großen BUNCH-Computerherstellers von 1971 mit dem Titel „Logik der Programmierung, Normierte Programmierung“, mit dem damals angehende Programmierer und Systemanalytiker ausgebildet wurden, waren die Ziele der normierten Programmierung Vereinheitlichung und Standardisierung der Programmerstellung, Verkürzung der Programmierzeit, Ausschaltung möglicher Fehlerquellen und damit Verkürzung der Testzeit und Senkung der Kosten für die Programmierer.
Kernstück der normierten Programmierung ist die Programmablaufsteuerung. Die normierte Programmierung erzwingt die logische und funktionelle Ordnung eines Programms durch eine vereinheitlichte Programmablaufsteuerung, die unabhängig vom jeweiligen Programmierer ist.
Der Programmablauf ist in Blöcke unterteilt, wobei jeder Block einen funktional zusammengehörigen Teil eines Programmes darstellt. Die Unterteilung stellt sozusagen den „natürlichen“ Aufbau eines kommerziellen Programms dar: Vor Beginn der eigentlichen Verarbeitung sind Anfangswerte zu setzen und Steuerinformationen auszuwerten, dann sind Eingabedaten zu lesen, der nächste Satz zur Verarbeitung ist auszuwählen, eventuell müssen Gruppenwechsel behandelt werden, schließlich ist der Datensatz zu verarbeiten und gegebenenfalls sind Daten auszugeben. Jeder Block stellt eine in sich geschlossene Einheit dar. Ein Block kann zur besseren Übersicht aus mehreren Unterblöcken bestehen. Der abgebildete Programmablaufplan zeigt folgende Blöcke:
Zum besseren Verständnis der Problematik der Datenzufuhr muss man sich vergegenwärtigen, wie ein Programm in Stapelverarbeitung (und nur diese gab es zu Zeiten der Erfindung der normierten Programmierung Ende der 1960er Jahre) aussah: Es gab fast ausschließlich sequentielle Dateien, die in einer bestimmten Sortierfolge vorliegen mussten. Mehrere Eingabedateien mussten Satz für Satz seriell in der richtigen Reihenfolge eingelesen und mit den passenden Sätzen der anderen Dateien abgemischt, verarbeitet, bei sequentiellen Plattendateien eventuell aktualisiert und ausgegeben werden. Die Dateien konnten als Lochkartenstapel, als Magnetbanddatei, als sequentielle Plattendatei und eventuell als Lochstreifen vorliegen. Plattendateien mit wahlfreiem Zugriff kamen erst Anfang der 1970er Jahre auf.
Das wesentliche Merkmal der normierten Programmierung ist die Automatik der Datenzufuhr. Bei der seriellen Eingabe von Daten aus mehreren Dateien liegt das Problem in der Auswahl des nächsten zu verarbeitenden Satzes. Der zentrale Schlüssel für die Steuerung des Programmablaufs ist der Gruppenbegriff, der in jedem Satz der Eingabedateien enthalten sein muss. Da die Gruppenbegriffe an unterschiedlichen Positionen der Eingabedateien liegen können, werden bei der normierten Programmierung die Gruppenbegriffe aus den Datensätzen herausgeholt und in separaten dateibezogenen Gruppenbegriffsfeldern von rechts nach links nach Gruppenstufen aufsteigend abgespeichert. Es gibt für jede Eingabedatei ein solches, bei allen Dateien gleich großes Gruppenbegriffsfeld – deshalb dateibezogen. Im Beispiel besteht das Gruppenbegriffsfeld der Eingabedatei 2 von rechts nach links aus der Dateinummer L2D („2“), den Gruppenbegriffen L21 (Untergruppenbegriff), L22 (Hauptgruppenbegriff, L23 (Übergruppenbegriff), L24 (ein nochhöherer Gruppenbegriff) und aus dem Feld L2S für den Dateistatus. Die Felder Ln1 bis Ln4 können gemeinsam als LnM zur Paarigkeitsprüfung herangezogen werden. Die Namen der Felder wurden in Anlehnung an die damals weit verbreitete Terminologie von RPG (Report Program Generator) vergeben (L für Level, Gruppenstufe).
Neben den dateibezogenen Gruppenbegriffsfeldern gibt es zwei weitere, dateineutrale Felder, die für die Gruppenkontrolle verwendet werden:
Die Größe stimmt mit der Größe der dateibezogenen Felder L0, L1, … voll überein. Lediglich die Definition der Felder ist aus Zweckmäßigkeitsgründen für die Gruppenkontrolle anders gewählt worden. Im Beispiel dient das Feld LN1 zur Kontrolle der Untergruppe, das feld LN2 der Kontrolle der Hauptgruppe usw.
Nach Eingabe eines Satzes von jeder Datei muss von allen Sätzen jener ausgewählt werden, der als nächstes verarbeitet werden soll. Bei unterschiedlichen Gruppenbegriffen ist die Lösung einfach, der Satz mit dem kleinsten Gruppenbegriff ist als nächster zu verarbeiten. Sind die Gruppenbegriffe jedoch gleich (paarig), muss entschieden werden, welche Datei die höhere Priorität hat, d. h. die Dateinummer bestimmt die Priorität. Bei dem klassischen Fall einer Gegenüberstellung von Stamm- (z. B. Teilestamm) und Bewegungsdaten (z. B. Lagerbewegungen) bestimmen die Bewegungsdaten, ob die Stammdaten bearbeitet werden müssen oder nicht, der Bewegungssatz muss also als erster verarbeitet werden. Die Dateinummer – eine Konstante – bestimmt bei Paarigkeit der restlichen Gruppenbegriffe über die Priorität, je kleiner die Dateinummer umso höher die Priorität.
Der Dateistatus unterscheidet vier Zustände:
Am Anfang stehen die Zustände aller Eingabedateien auf 0 („Satz nachziehen“). Nach dem Nachziehen einer Datei wird ihr Status auf 1 gesetzt. Erst wenn sie zur Verarbeitung freigegeben wird, wird der Status wieder auf 0 gesetzt. Der Status 3 kann z. B. auf Grund von Vorlaufdaten Ablaufvarianten mit unterschiedlichen oder vorhandenen/nicht vorhandenen Dateien steuern.
Die beiden Felder am rechten und linken Rand der Gruppenbegriffsfelder haben also eine besondere Bedeutung, die Dateinummer musste wohl überlegt sein, insbesondere bei seriell zu verarbeitenden sogenannten Update-Dateien wie Lesestanzern (Lochkartenleser und -stanzer in einem Gerät) oder Plattendateien. Ihnen gebührte die kleinste Priorität (= höchste Dateinummer), weil sie von allen anderen Sätzen der gleichen Gruppe eine Veränderung erfahren mussten.
Hier wurden sogenannte Vorlaufkarten gelesen, mit denen das Programm gesteuert wurde, Laufvarianten ausgewählt, das Laufdatum gesetzt, Dateien (mit dem Befehl OPEN) eröffnet, Tabellen geladen, Schalter gesetzt, kurz alle einmaligen Arbeiten vor Beginn des Programmzyklusses.
Der Block B ist je nach der Anzahl der sequentiellen Eingabedateien in Unterblöcke B0, B1, B2, … unterteilt, die nacheinander durchlaufen werden. Je nach Dateistatus wird ein Satz nachgelesen oder nicht. Nach der Eingabe erfolgt die Prüfung auf Dateiende. Falls nicht werden die dateispezifischen Gruppenbegriffsfelder beschickt und der Dateistatus auf „nicht nachziehen“ gesetzt. Da man nicht sicher sein konnte, dass eine Eingabedatei auch wirklich in der richtigen Sortierfolge war (ein Stapel Lochkarten konnte dem Operator aus der Hand gefallen sein), erfolgte in diesem Block auch eine Reihenfolgekontrolle oder andere Plausibilitätsprüfungen.
Im Block C erfolgte auf Grund der Inhalte der Gruppenbegriffsfelder die Auswahl und Freigabe des nächsten zu verarbeitenden Satzes. Ab wann und wie lang (i. S. von Block G) Datensätze ‚verfügbar‘ sind, hängt von der Verwendung dateibezogener Workbereiche ab und sollte in der Implementierung der Steuerungslogik genau festgelegt werden.
Die Gruppenkontrolle erfolgt mit Hilfe der dateineutralen Gruppenbegriffsfelder LN und LA. Zur Prüfung eines Untergruppenwechsels werden LN1 und LA1 verglichen, für eine Gruppenwechsel LN2 und LA2 usw. Bei Gruppenstufenwechseln werden Unterprogramme des Blocks G aufgerufen (G1, G2, G3, …).
Hier wird verarbeitet, was am Ende bzw. am Anfang eines jeden Gruppenbegriffs zu tun ist. Aufruf nur für die in Block D festgestellten Gruppenstufen, zuerst die Wechsel (von unten nach oben), dann die Vorläufe (von oben nach unten). Je Gruppenbegriff wird nach Gruppen-Vorlauf (Beispiel: Ausgabe einer Listen-Kopfzeile) und Gruppen-Wechsel (Beispiel: Ausgabe von Summen) unterschieden. Die Ausführung der Vorläufe und der Wechsel liegt zeitlich weit auseinander.
Im Block E erfolgt die Verarbeitung der einzelnen Sätze aus den steuernden Eingabedateien. Nachdem die Zuständigkeit des Unterblocks (E1, E2, …) festgestellt ist werden je nach Satzart Daten zwischengespeichert, kumuliert, ausgegeben (durch Aufruf eines Unterprogrames des J-Blockes), Schalter zurückgesetzt (z. B. QL1, QL2, QG1, QG2, … auf die Schalter der normierten Programmierung wird hier nicht eingegangen), usw.
„Die häufige Verwendung von Unterprogrammen ist sehr zu empfehlen. Selbst wenn ein bestimmter Verarbeitungsteil im Programm nur einmal vorkommt, kann es sinnvoll sein, diesen Teil in ein Unterprogramm auszulagern, um die Ablauflogik des Verarbeitungsprogramms entsprechend klar und übersichtlich herauszuarbeiten.“ („Logik der Programmierung – Normierte Programmierung“ SPERRY UNIVAC um 1970)
Es wurde dringend empfohlen, alles was zur Ausgabe im weitern Sinn gehört, in diese Unterprogramme auszulagern, also z. B. Druckbereiche löschen, bei Randomdateien die Satzadresse berechnen, Steueranweisungen für bestimmte Geräte absetzen usw.
Hierzu gehört das Schließen von Dateien, die Ausgabe von z. B. Schlusssummen und die Beendigung des Programms.
Die Programmierzeit wurde im Vergleich zur „wilden“ Programmierung wesentlich verkürzt, ebenso die Testzeit. Das System ist relativ einfach zu erlernen, ist unabhängig von Maschinentypen und Programmiersprachen und unabhängig von den jeweiligen Programmierern (entsprechend wurde es von „Künstlern“ auch gerne abgelehnt). Jemand der die Methode der normierten Programmierung kennt, kann sich schnell in ein fremdes Programm, das dieser Methodik folgt, einarbeiten.
Die Namensvergabe war ein weiteres Feld, bei dem Standardisierung angestrebt wurde, aber grundsätzlich haben wilde, auf den ersten Blick (oft auch noch beim dritten Blick) unsystematische Namen nichts mit Normierter Programmierung zu tun, genauso wenig wie Spaghettiprogramme oder gehäuft auftretende „GO TO“s. An einige Konventionen sollte man sich jedoch halten, zum Beispiel an die Namen für Schalter (QL1, QG1…), Blöcke (A-…, B1-…, E1-Personalstamm-…, etc.), die Verwendung von verschiedenen Präfix für Konstanten (K…), Gruppenbegriffsfelder (L…), Schalter (Q…) usw.
Ende der 1969er und in den 1970er Jahren drehte sich die Diskussion um Top-down-Vorgehensweise, schrittweise Verfeinerung und modulare Programmierung. Insbesondere die Vorschläge von E. W. Dijkstra zur strukturierten Programmierung wirken bis heute, konnten aber schon damals innerhalb von normierten Programmen realisiert werden. Einer schrittweisen Verfeinerung vor allem der Blöcke E, H und J stand die normierte Programmierung nicht im Wege. Die elementaren Grundstrukturen waren z. B. in COBOL verfügbar, ein „GO TO“-freies Programm mit normierter Programmierung war möglich, das Blockkonzept war also auch mit COBOL, ja sogar mit Assembler möglich. Der Lesbarkeit der Programme setzen bis heute die einzelnen Programmierer Grenzen, auch in C und Java, lediglich die Beschränkung der Datenverfügbarkeit war nur über separat kompilierte Programmmodule möglich.