COBOL modern

Ich habe COBOL noch zu Zeiten des ANSI-74 Standards kennengelernt, hier fehlten etliche Dinge, die eine moderne Programmiersprache auszeichnet. Aber seit gut 25 Jahren ist COBOL-85 verfügbar. Hier sind alle notwendigen Statements vorhanden, um gut strukturierte Programm zu erstellen, in einigen Bereichen ist COBOL sogar weiter wie andere Sprachen, das EVALUATE fehlt mir zum Beispiel in JAVA.

Die Verteufelung des Befehls GOTO kann ich nicht verstehen, auch wenn ich sehr gut ohne einen Sprungbefehl programmieren kann (ich habe lange Jahre in dBase, Clipper und xBase++ programmiert, dort gibt es keinen Sprungbefehl). Sicher war es zu der Zeit, wo die Kollegen, die mit COBOL-74 arbeiten mussten und hier mit dem GOTO Spaghetti Code schrieben, wichtig, den Gebrauch von GOTO in der alten Weise zu verhindern. Aber jede Anweisung innerhalb einer Section in ein

IF KEIN-FEHLER

END-IF

zu setzen, oder extrem kleine Sections zu schneiden, verunstaltet die Programme und erschwert den Überblick über den Programmfluss.

Der Einsatz des Befehls GOTO mit einem Sprungziel in der gleichen Section weiter unten ist sinnvoll. Das Werfen einer Exception in Java ist ja auch ein GOTO bis zu der Stelle, wo die Exception aufgefangen wird.

Der Aufbau einer Section nach folgendem Muster hat sich bewährt:

MySection section.
Start.
Anweisungen

if Ein-Fehler-Ist-Aufgetreten goto FehlerVerarbeitung end-if
...
goto Ende.
FehlerVerarbeitung.

contiune.
Ende.
exit.

Die Namen einer Paragraphen in jeder Section sollten identisch sein, also "Start.", "FehlerVerarbeitung." und "Ende.". Es macht das Kopieren von Programmzeilen einfacher und vor allem meldet der Compiler einer Fehler, wenn das Sprungziel nicht in der Section definiert ist, da er kann in den anderen Sections viele Paragraphen mit dem Namen finden.

Ein Kollege in einem Projekt umging das GOTO mit dem Befehl "NEXT SENTENCE", also ein GOTO bis nach dem nächsten Punkt. Sofern eine Section nur zwei Paragraphen hat, der zweite Paragraph nur aus einen "EXIT." besteht und Punkte nur beim Paragraphen sowie den jeweils letzten Statement vorkommen, ist alles super. Ich hatte nach dem Ausscheiden des Kollegen aus dem Projekt seine Programme übernommen, wusste von seinem Vorgehen nichts und kopierte eine Abfolge von Statements aus einem anderen, älteren Programm in eine Section. In den älteren Programm (wohl in den 1980zigern entstanden) waren, die früher übliche, alle Statements mit einem Punkt beende. Bis ich das Problem erkannte, dauerte es etwas.

Der Punkt in COBOL ist wichtig, aber kann leicht übersehen werden. Am Ende der Section- oder Paragraphen-Definition muss ein Punkt stehen und dort sieht man ihn auch. Nach nach einem EXIT oder einem GOBACK steht ein Punkt. Ansonsten sollte der Punkt am Ende eines Paragraphen nicht am letzten Statement stehen, sondern in einer eigenen Zeile mit der "Blickfang" "CONTINUE.".

Vielfach werden in COBOL-Programmen nur Grossbuchstaben verwendet. Zu Zeiten von Lochkarten und vor allem Kettendruckern, die meist keine Kleinbuchstaben drucken konnten, hatten die Kollegen auch keine andere Möglichkeit. Eine Schreibweise mit COBOL-Statements in Kleinbuchstaben und Namen in "Camelback" Schreibweise, z.B.

move DerErsteWert to DerZweiteWert

hat sich in Projekten bewährt.

Was ist auf den ersten Blick verständlicher?
move Humus to blumentopferde
oder
move Humus to BlumentoPferde
oder
move Humus to BlumenTopfErde

Insbesondere wenn Teile des Projektes in Java implementiert werden, sollten die Variablen die gleichen Namen haben und identisch geschrieben werden.

Über das Einrücken und seinen Sinn brauche ich wohl kein Wort zu verlieren. Leider gab es einige Kollegen, die den Sinn nicht erkannt hatten. Diese Programm in Form zu bringen ist zwar zuerst etwas Arbeit, die Zeit kostet. Aber im Anschluss gewinnt man bei der Wartung deutlich an Zeit.

Ein Problem von COBOL ist, dass es in einem Programm nur einen globalen Namensraum gibt. Hiermit kann man leben. Die Verwendung des COPY REPLACING beim Einbinden einer Copystrecke vereinfacht das Programmieren. Leider kennt der INCLUDE des SQL-Präprozessors kein REPLACING. Dann muss mit dem "IN" oder "OF" zum Qualifizieren gearbeitet werden. In Projekten hat sich die Verwendung von "IN" für das Qualifizieren und die Verwendung von "OF" für Adressen (Pointer) als gut herausgestellt.

Eine weitere Möglichkeit, Namensraume zu unterteilen sind Unterprogramme, die per CALL aufgerufen werden. Diese können als eigenständige Lademodule vorliegen, als Embedded Unterprogramme per Copy-Anweisung eingebunden werden oder direkt in das Programm geschrieben werden.

Als Befürworter des dynamischen Linkens sehe ich Vorteile bei der Verwendung von eigenständigen Lademodulen. Bei sehr zeitkritischen Anwendungen kann das Einbinden in die Source des Hauptprogramms Zeitvorteile bringen, die den Nachteil, dass bei einer Änderung ein einem Embedded Unterprogramm alle betroffenen Programme neu zu übersetzen sind, ausgleicht.