Die normierte Programmierung beschreibt eine standardisierte 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. Für Programme mit solchen Aufgaben lässt sich dieses Schema unabhängig von der fachinhaltlichen Aufgabenstellung und 'technologieneutral' (z. B. in jeder Programmiersprache) anwenden.
Historischer Rückblick
Zum besseren Verständnis der Entstehung der Normierten Programmierung sollte man sich vorstellen, wie Stapelprogramme (und nur solche gab es zu Zeiten der 'Erfindung' der normierten Programmierung Ende der 1960er Jahre) aussahen: Es gab praktisch nur sequentielle Dateien - in denen oft unterschiedliche 'Satzarten' gemischt / hintereinander auftraten, weil z. B. nur 1 Magnetbandstation oder 1 Lochkartenleser für die Eingabe verfügbar war. Ein Mischen im Programm war so nicht erforderlich - und wäre bei Arbeitsspeichern von z. B. 64 KB inkl. Betriebssystem auch zu aufwändig gewesen. So las das Programm 'seine' Datei und verarbeitete die Daten abhängig von der 'Satzart'. Das Programm 'lief' (mit GOTO) je nach Datenkonstellation zu bestimmten Stellen, zum Beispiel zu Rechenvorgängen, zum Drucken einer Listenzeile, um Daten nachzulesen - oder letztlich zum Programmende. Die Programme waren oft 'Spaghetticode', folgten kaum einheitlichen Strukturvorgaben und waren deshalb intransparent, fehleranfällig und änderungsunfreundlich.
Leistungsfähigere Rechner, neue Programmiersprachen, aber auch die Arbeiten von Methodenentwicklern führten sukzessive zu besseren Verfahren: Es entstanden Vorschläge für eine standardisierte Struktur von Stapelprogrammen. Darin war die gesamte Steuerung des Programms in eindeutig definierte 'Routinen' zergliedert, die die aufgabenspezifischen Verarbeitungsteile des Programms aufrufen – die 'Normierte Programmierung'.
Allerdings werden in der Praxis der (individuellen) Softwareentwicklung derart standardisierte Verfahren oft nicht angewendet – mit der Folge, dass das Erstellen des Programmcodes zur Programmsteuerung in vielen Fällen eine besondere Herausforderung bzw. 'Problemstellung' für die Entwickler blieb, die nicht selten hohen Entwicklungaufwand verursacht und beim Softwaretest Fehler zutage fördert.
Zielsetzung
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.
Die normierte Programmierung
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.
Das Schema der Programmablaufsteuerung
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:
- A: Vorprogramm für alle einmalig durchzuführenden Programmschritte
- B: Eingabe; sie besteht aus soviel Unterblöcken wie es serielle Eingabedateien gibt. In jedem dieser Blöcke wird nicht nur die eigentliche Eingabe abgehandelt sondern auch Plausibilitätsprüfungen und Reihenfolgekontrolle.
- C: Satzfreigabe; aus den gelesenen Sätzen je Datei wird ausgewählt, welcher Datensatz als nächster zu verarbeiten ist - und (vorher) zur Feststellung von Gruppenwechseln verwendet wird.
- D: Gruppenkontrolle und Aufruf der Gruppenwechsel-Unterprogramme für alle Gruppenstufen.
- E: Einzelverarbeitung; sie ist wiederum entsprechend der Anzahl Eingabedateien in Unterblöcke unterteilt.
- F: Schlussprogramm für alle einmalig nach dem eigentlichen Programmablauf zu durchlaufenden Programmbefehle.
- G: Unterprogramme der Gruppenverarbeitung; es gibt soviele Unterprogramme wie es Gruppenstufen gibt, jeweils für Vorläufe und Nachläufe getrennt.
- H: Unterprogramme der Einzelverarbeitung; diese Unterprogramme sollten möglichst klein und übersichtlich sein.
- J: Unterprogramme der sequentiellen Ausgabe und der wahlfreien Ein-/Ausgabe; für jede der genannten Dateien gibt es ein Unterprogramm.
Die Datenzufuhrsteuerung
Eine wesentliche Teilfunktion in der 'Normierten Programmierung' ist die Automatik der Datenzufuhr. Aus den Eingabedaten aller Dateien wird jeweils der als nächstes zu verarbeitende Satz ermittelt und der Verarbeitung zugeführt. Anschließend wird exakt aus dieser Datei wieder nachgelesen. Umgesetzt wird diese Art der Datenzufuhr in den Blöcken Eingabe und Satzfreigabe.
Gruppenbegriffsfelder
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 links nach rechts nach der Gruppenstufenhierarchie absteigend gespeichert. Es gibt für jede Eingabedatei ein solches, bei allen Dateien gleich großes und gleich-formatiges 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:
- LA enthält den Gruppenbegriff des letzten verarbeiteten Satzes
- LN enthält den Gruppenbegriff des nächsten zu verarbeitenden Satzes
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.
Die Datei-Nummer
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 Datei-Status
Der Dateistatus unterscheidet vier Zustände:
- 0 = Satz nachziehen
- 1 = Satz nicht nachziehen
- 2 = Datei abgeschlossen
- 3 = Datei nicht vorhanden
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.
Der Steuerungsmechanismus
Die Steuerung des Programms geschieht (grob) nach der Logik wie sie im Schaubild 'Blockunterteilung der normierten Programmierung' dargestellt ist. Von hier aus werden alle Subroutinen der Verarbeitung (A bis G) angesteuert. Grundlage dazu sind die dateibezogenen und die dateineutralen Gruppenbegriffsfelder, wie sie beim Lesen und in der Satzfreigabe bereitgestellt werden.
Der Aufbau der Blöcke
Block A: Vorprogramm
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.
Block B: Eingabe
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. Direkt nach dem Lesen erfolgt die Prüfung auf Dateiende. Falls ja, wird der Dateistatus auf "Dateiende" gesetzt, andernfalls auf „nicht nachziehen“ und die dateispezifischen Gruppenbegriffsfelder werden gefüllt.
Wenn nicht gesichert ist, dass eine Eingabedatei immer in der richtigen Sortierfolge vorliegt, sollte in diesem Block eine Reihenfolgekontrolle oder andere Plausibilitätsprüfungen stattfinden - ggf. mit vorzeitigem Programmabbruch.
Auch kann hier evtl. ein 'Filtern', d.h. Überlesen bestimmter Datensätze stattfinden - die damit auch keine Gruppenwechsel auslösen.
Block C: Satzfreigabe
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.
Block D: Gruppenkontrolle
Die Gruppenkontrolle erfolgt mit Hilfe der dateineutralen Gruppenbegriffsfelder LN und LA. Zur Prüfung eines Gruppenwechsels der niedrigsten Stufe wird LN1 gegen LA1 (siehe Schaubild 'Dateineutrales Gruppenbegriffsfeld') verglichen, für einen Wechsel der zweitniedrigsten Stufe LN2 gegen LA2 usw. - bis zur höchsten Gruppenstufe.
Für festgestellte Gruppenwechsel werden die Unterprogramme des Blocks G aufgerufen, und zwar zunächst die Gruppen-Nachläufe (außer nach dem ersten Lesen; von der niedrigsten Stufe bis zur festgestellten Wechselstufe) und danach die Gruppen-Vorläufe (außer nach der Verarbeitung aller Datensätze; von der festgestellten Wechselstufe bis zur niedrigsten).
Block G: Gruppenverarbeitung
Hier wird verarbeitet, was am Ende bzw. am Anfang eines jeden Gruppenbegriffs zu tun ist. Je Gruppenbegriff wird nach Gruppen-Vorlauf (Beispiel: Ausgabe einer Listen-Kopfzeile) und Gruppen-Nachlauf (Beispiel: Ausgabe von Summen) unterschieden. Die Aufrufe erfolgen aus Block D nur für die festgestellten Gruppenstufen.
Beachte: Die Ausführung des Vorlaufs und des Nachlaufs für einen konkreten Gruppenbegriff (z. B. PLZ 12345) liegt zeitlich weit auseinander; dazwischen liegt mindestens eine Einzelverarbeitung, ggf. auch die Gruppenverarbeitung niedrigerer Gruppenstufen.
Block E: Einzelverarbeitung
In den Unterroutinen des Blocks E werden die Sätze aus den steuernden Eingabedateien verarbeitet. Es wird genau der Datensatz (je nach Datei in Unterblock E1, E2 usw.) verarbeitet, der in der Satzfreigabe (Block C) ausgewählt wurde; die Dateinummer steht im Feld LND. Evtl. erforderliche (alte) Gruppen-Nachläufe und (neue) Gruppen-Vorläufe sind zu diesem Zeitpunkt bereits verarbeitet.
Je nach Aufgabenstellung, Satzart etc., werden z. B. Daten zwischengespeichert, Summen berechnet und kumuliert, Daten / Einzelzeilen ausgegeben (durch Aufruf eines Unterprogrames des J-Blockes), Schalter gesetzt (z. B. QL1, QL2, QG1, QG2, … auf die Schalter der normierten Programmierung wird hier nicht eingegangen) usw.
Achtung! Ob Datensätze aus anderen Dateien bereits gelesen, verarbeitet, zwischengespeichert usw. sind, hängt von deren 'Dateinummer' (Feld LxD) ab; Bezugnahme auf Inhalte 'fremder' Datensätze ist nur möglich wenn diese Dateien höhere Priorität aufweisen.
Block H: Unterprogramme der Verarbeitung
„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)
Block J: Unterprogramme der seriellen Ausgabe und wahlfreien Ein-/Ausgabe
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.
Block F: Schlussprogramm
Hierzu gehört das Schließen von Dateien, die Ausgabe von z. B. Schlusssummen und die Beendigung des Programms.
Die besonderen Merkmale der normierten Programmierung
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.
Hilfsmittel für die Normierte Programmierung
Zur Erstellung eines Programms nach 'Normierter Programmierung' sollten Hilfsmittel angewendet werden, mit denen der Aufwand zur Programmerstellung minimiert und die Qualität der erstellten Programme (z. B. Richtigkeit, Testbarkeit, Einheitlichkeit) erhöht bzw. gesichert werden kann. Hierzu zählen:
- Programmgeneratoren: Im Systemsoftwaremarkt sind Generatoren verfügbar, mit denen auf der Basis zu definierender Vorgaben ein Programmrahmen erzeugt werden kann. Dieser enthält i.d.R. die komplette Programmsteuerung mit allen dazu erforderlichen Datenfeldern und den von der Hauptsteuerung angesprochenen Unterroutinen (Eingabe, Gruppenkontrolle und -Verarbeitung, Verarbeitung usw.). Oft unterstützen diese Generatoren nur bestimmte Programmiersprachen. Auch werden die Datenfelder und Unterroutinen i.d.R. generator-spezifisch nach anderen als den HIER gezeigten Namenskonventionen erzeugt.
- Programmtemplates: Wenn kein Generator verfügbar ist, ist ein Muster-Programmrahmen hilfreich, der ähnliche Strukturen wie unter 'Programmgeneratoren' genannt (und weitere Unternehmensstandards berücksichtigend) bereitstellt. Beim Erstellen eines neuen Programms wird der Rahmen kopiert, individuell auf die Aufgabenstellung (Anzahl Dateien und Gruppenbegriffe) angepasst.
In beiden Fällen liegt (nach den vorgenannten Startaktivitäten) die gesamte Ablaufsteuerung fertig vor, der Programmierer muss 'nur noch' die aufgabenspezifischen Verarbeitungsdetails in den noch leeren Unterroutinen (wie Gruppenvorlauf_1, Einzelverarbeitung_A usw.) einstellen. Je nach eingesetztem Verfahren, Programmiersprache etc. können Details der Standardlogik (etwa das Feststellen von Gruppenwechseln, die Bezeichnung von Feldnamen etc.) unterschiedlich, jedoch immer zu gleichem Ablauf führend, implementiert sein.
Weitere Standardisierungen
Eine wörtliche Auslegung von 'Normierte Programmierung' könnte alle normierenden / standardisierenden Aspekte der Programmierung (= das Erstellen eines Computerprogramms im engeren Sinn) umfassen. Dazu können, neben der normierten Ablaufsteuerung (wie in diesem Artikel beschrieben) folgende Aspekte gehören:
- Namenskonventionen: HIER i.W. als Vorschlag für die Benennung der Funktionsblöcke beschrieben. Regeln für die Benennung von Datendefinitionen sollten ebenfalls im Detail vorgegeben sein.
- GOTO-freie Programmierung: Abhängig von der verwendeten Programmiersprache werden hierfür Schleifenkonstrukte angeboten. Ziel hierbei ist eine übersichtliche Programmlogik. Zumindest sollten direkte Sprünge in fremde Subroutinen niemals erlaubt sein, d.h. jede Subroutine springt zu ihrem Aufrufpunkt zurück.
- Standard-Funktionen: In vielen Unternehmen existieren für bestimmte Aufgaben (technisch / fachlich) vorgefertigte Routinen (Unterprogramme, Makros, Codesequenzen ...), die in individuellen Programmen zu verwenden sind. Beispiele: Open / Close, Datumberechnung, Druckausgabe ...
- Standard-Datendefinitionen: Die Struktur von Datensätzen (ihre Feldfolge, Länge, Formate ...) sollte immer in einer Form vorliegen, die in allen diese Dateien verarbeitenden Programmen verwendet wird. Hierbei sollte es z. B. möglich sein, für die Eingabe einen anderen Präfix zu verwenden als für die Ausgabe.
- Gestaltung von Bildschirminhalten: Farben, Position von Eingabefeldern und Fehlermeldungen ...
- Gestaltung von Listen: Anordnung von Kopf- und Fußzeilen ...
- Programmkommentare: In einigen Unternehmen ist vorgeschrieben, die erstellten Befehle sehr detailliert zu kommentieren. Achtung - Gefahr der Redundanz zu anderen schriftlichen Vorgaben.
- (Sicher ließen sich hier weitere Aspekte mit Normierungs-Charakter aufzählen)
Die Misserfolge bei den zahlreichen Versuchen nationaler oder gar weltweiter Standardisierung sollte die Unternehmen nicht davon abhalten, entsprechende Vorgaben als innerbetriebliche Regeln aufzustellen - und deren Einhaltung (als Teil der Qualitätssicherung) zu überprüfen.
Normierung / Standardisierung ist ein wesentlicher Aspekt von Qualität. Siehe auch Programmierstil.
Kritik und Weiterentwicklungen
Ende der 1960er 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 den einzelnen Programmierern Grenzen, auch in C und Java, lediglich die Beschränkung der Datenverfügbarkeit war nur über separat kompilierte Programmmodule möglich.
Den Ansatz der 'Normierten Programmierung' wird auch durch die Tatsache bestätigt, dass viele Reportgeneratoren und Datenbank-Auswertungssprachen strukturell nahezu identische Konstrukte verwenden: Der Benutzer kennt und definiert hier z. B. Listenkopf und -Fuß (entsprechend Programmvorlauf und -Ende), Gruppenkopf und Gruppenfuß (entsprechend Gruppenvorlauf und Gruppennachlauf) für mehrere, hierarchisch definierte Gruppenstufen. Die Einzelzeile (auch Detailbereich genannt) zeigt Informationen über den einzelnen Datensatz, was der Einzelverarbeitung entspricht.