Programmieren
10.03.2004, 00:00 Uhr
COBOL als Sprache im .NET-Framework
Die auf kaufmännische Anwendungen zugeschnittene Programmiersprache COBOL steht nun auch für das .NET-Framework zur Verfügung: Der Compiler von Micro Focus erzeugt direkt Managed Code. Auf dieser Basis lässt sich die Brücke von prozeduraler zu objektorientierter Programmierung schlagen.
von Rolf Becking
Wenn von Programmiersprachen für das .NET-Framework die Rede ist, denkt man normalerweise an C#, C++ oder VB.NET, aber vermutlich nicht an den Programmierklassiker COBOL. Dabei gehört es zu den Besonderheiten von .NET, die Softwareentwicklung ein wenig von ihrer Orientierung auf einzelne Sprachen zu lösen und eine einheitliche Plattform für ein möglichst großes Spektrum an Programmiersprachen zur Verfügung zu stellen. Damit soll es möglich sein, die Entwicklung stärker an funktionalen als an technischen Aspekten auszurichten: jeder Programmierer soll die Sprache verwenden können, die der Aufgabe am besten entspricht und mit der er am produktivsten arbeiten kann.
Damit ist auch schon COBOL im Spiel, denn diese Sprache eignet sich ganz hervorra-gend zur Abbildung von Business-Prozessen: Sie bietet beispielsweise eine spezielle Dezimal-Arithmetik, Satzorientierte Datentypen und ist auf die schnelle Verarbeitung von Massendaten, wie sie bei kaufmännischen Anwendungen üblich sind, eingerichtet. Für diesen Einsatzbereich wurde COBOL über Jahrzehnte optimiert, so dass ihr bis heute hinsichtlich Performance und Stabilität keine andere Programmiersprache das Wasser reichen kann.
Dazu kommt, dass in den Unternehmen eine riesige Menge an COBOL-Applikationen in Betrieb ist, weshalb laufend Code weiterentwickelt und gepflegt werden muss. Insofern wird COBOL-Entwicklern die Arbeit so bald nicht ausgehen. Auf der anderen Seite hat sich modernes COBOL von der Entwicklung von Front-Ends und Benutzerschnittstellen weitgehend verabschiedet; es mag technisch möglich sein, ein GUI auch in COBOL zu designen, hier aber haben andere Sprachen eindeutig die Nase vorn. Nimmt man beide Aspekte zusammen, so liegt die Notwendigkeit einer gemischtsprachigen Entwicklung auf der Hand, und das .NET-Framework ist die Plattform auf der sich COBOL und die neuen Sprachen treffen.
Seit neuem ist COBOL tatsächlich auch als vollgültige .NET-Sprache verfügbar. Mit "Net Express with .NET" von Micro Focus ist es möglich, aus COBOL-Code direkt MSIL (Microsoft Intermediate Language) zu generieren und das fertige Compilat unter Kontrolle der CLR (Common Language Runtime) ablaufen zu lassen. Damit eröffnen sich für Anwender zwei interessante Szenarien:
Für die Praxis ist ein Aspekt besonders wichtig: man muss keineswegs alles neu machen, wenn man COBOL unter .NET laufen lassen möchte. Im Gegenteil, COBOL-Programme können ohne Änderungen im Source-Code einfach recompiliert und als Managed Code unter .NET ausgeführt werden. Der COBOL-Compiler von Net Express compiliert COBOL-Programme, gleichgültig ob schon vorhanden oder neu codiert, zur MSIL. Probleme können allerdings auftauchen, wenn vorhandene (Mainframe-)Applikationen nicht nur aus reinem COBOL-Code bestehen, sondern außerdem Teile enthalten, die in Assembler programmiert wurden oder proprietäre Datenhaltungssysteme und Transaktionsmonitore verwenden.
Wenn von Programmiersprachen für das .NET-Framework die Rede ist, denkt man normalerweise an C#, C++ oder VB.NET, aber vermutlich nicht an den Programmierklassiker COBOL. Dabei gehört es zu den Besonderheiten von .NET, die Softwareentwicklung ein wenig von ihrer Orientierung auf einzelne Sprachen zu lösen und eine einheitliche Plattform für ein möglichst großes Spektrum an Programmiersprachen zur Verfügung zu stellen. Damit soll es möglich sein, die Entwicklung stärker an funktionalen als an technischen Aspekten auszurichten: jeder Programmierer soll die Sprache verwenden können, die der Aufgabe am besten entspricht und mit der er am produktivsten arbeiten kann.
Damit ist auch schon COBOL im Spiel, denn diese Sprache eignet sich ganz hervorra-gend zur Abbildung von Business-Prozessen: Sie bietet beispielsweise eine spezielle Dezimal-Arithmetik, Satzorientierte Datentypen und ist auf die schnelle Verarbeitung von Massendaten, wie sie bei kaufmännischen Anwendungen üblich sind, eingerichtet. Für diesen Einsatzbereich wurde COBOL über Jahrzehnte optimiert, so dass ihr bis heute hinsichtlich Performance und Stabilität keine andere Programmiersprache das Wasser reichen kann.
Dazu kommt, dass in den Unternehmen eine riesige Menge an COBOL-Applikationen in Betrieb ist, weshalb laufend Code weiterentwickelt und gepflegt werden muss. Insofern wird COBOL-Entwicklern die Arbeit so bald nicht ausgehen. Auf der anderen Seite hat sich modernes COBOL von der Entwicklung von Front-Ends und Benutzerschnittstellen weitgehend verabschiedet; es mag technisch möglich sein, ein GUI auch in COBOL zu designen, hier aber haben andere Sprachen eindeutig die Nase vorn. Nimmt man beide Aspekte zusammen, so liegt die Notwendigkeit einer gemischtsprachigen Entwicklung auf der Hand, und das .NET-Framework ist die Plattform auf der sich COBOL und die neuen Sprachen treffen.
Seit neuem ist COBOL tatsächlich auch als vollgültige .NET-Sprache verfügbar. Mit "Net Express with .NET" von Micro Focus ist es möglich, aus COBOL-Code direkt MSIL (Microsoft Intermediate Language) zu generieren und das fertige Compilat unter Kontrolle der CLR (Common Language Runtime) ablaufen zu lassen. Damit eröffnen sich für Anwender zwei interessante Szenarien:
- Übernahme von COBOL-Legacy-Applikationen in die .NET-Welt und Erweiterung dieser Applikationen durch .NET-Technologie, etwa durch die Verwendung der .NET-Framework-Klassen; durch die immens gestiegene Rechnerleistung ist es heute beispielsweise möglich, gestandene Mainframe-Anwendungen auch auf Windows-Systemen performant zu betreiben.
- Erweiterung von VB.NET oder C#-Programmen um bewährte COBOL-codierte Businesslogik.
Für die Praxis ist ein Aspekt besonders wichtig: man muss keineswegs alles neu machen, wenn man COBOL unter .NET laufen lassen möchte. Im Gegenteil, COBOL-Programme können ohne Änderungen im Source-Code einfach recompiliert und als Managed Code unter .NET ausgeführt werden. Der COBOL-Compiler von Net Express compiliert COBOL-Programme, gleichgültig ob schon vorhanden oder neu codiert, zur MSIL. Probleme können allerdings auftauchen, wenn vorhandene (Mainframe-)Applikationen nicht nur aus reinem COBOL-Code bestehen, sondern außerdem Teile enthalten, die in Assembler programmiert wurden oder proprietäre Datenhaltungssysteme und Transaktionsmonitore verwenden.
COBOL-Entwicklung mit der IDE Visual Studio: So gliedern sich im Solution Explorer COBOL-Programme in ein Projekt ein.
In diesem Fall reicht eine bloße Neu-Compilierung nicht aus, vielmehr muss die Applikation an die neue Umgebung angepasst werden, was meist mit Aufwand verbunden ist. Wenn es ein Trost ist: Immerhin wird man auf diese Weise (endlich) veraltete Technologie los. Auf Basis des .NET-Framework bieten sich jedenfalls genügend Alternativen an. Wurden früher Funktionalitäten, die in COBOL nicht realisiert werden konnten, häufig in Assembler programmiert, so hat man heute unter anderen die Auswahl zwischen C#, ASP.NET oder VB.NET. Daneben bietet das .NET-Framework bekanntlich einen großen Fundus an fertiger Software, aus dem man sich bedienen kann.
Prozedural oder objektorientiert
Bleibt die zentrale Frage, wie ein COBOL-Programm überhaupt in einer .NET-Umgebung lebensfähig sein kann, die prozedurale COBOL-Logik muss schließlich mit der rein objektorientierten .NET-Welt in Einklang gebracht werden. Eine Programmier-Philosophie, in der Absonderlichkeiten wie "Klassen" überhaupt nicht vorkommen, muss mit einer .NET-Framework-Klasse arbeiten können.
Zum Glück ist das moderne COBOL nicht mehr jenes COBOL, das zu lernen .NET-Anhänger sich einst geweigert hatten. Mit dem neuen, im Jahre 2002 verabschiedeten ISO-COBOL-Standard haben objektorientierte Konzepte erstmals auch offiziell Eingang in die klassische COBOL-Syntax gefunden. Sie erlauben nun die Verwendung von Klassen und deren Methoden in einem prozeduralen COBOL-Programm sowie die Definition von Klassen in COBOL selbst.
Wie das genau funktioniert, lässt sich am einfachsten mit einigen konkreten Beispielen zeigen; sie sind einem COBOL-Programm entnommen, das Methoden der .NET-Framework-Klassen benutzt. Die verwendeten Klassen müssen zunächst im COBOL-Programm im Repository-Paragraphen referenziert werden:
REPOSITORY.
CLASS StringClass As "System.String"
Damit wird die zu verwendende Klasse benannt und mit einem programminternen Namen verknüpft. Die nächste Anweisung:
01 numberString OBJECT REFERENCE StringClass.
legt ein Datenelement vom Typ "OBJECT REFERENCE" an, mit dem die Objekte und Methoden der jeweiligen Klasse angesprochen werden können. Dabei wird die Klasse festgelegt, auf die mit dieser Object Reference zugegriffen werden kann.
Mit der COBOL-Anweisung "INVOKE" können Methoden von Klassen aufgerufen werden. Im folgenden Beispiel wird die Methode "ToString" aus einer anderen Klasse aufgerufen, die eine Referenz auf ein Objekt der Klasse "StringClass" zurückliefert:
INVOKE ConvertClass "ToString" USING
BY VALUE numberValue
RETURNING numberString
Jetzt kann auf das durch "numberString" referenzierte Objekt der StringClass zugegriffen werden, um den enthaltenen String in eine TextBox der Winforms-Klasse zu übertragen, die dann in einem Fenster auf dem Bildschirm zur Anzeige gebracht werden kann.
SET TextProperty OF onHandNumber TO numberString
Dem klassischen COBOL-Programmierer ist diese Art der Syntax zwar vertraut, erfordert aber das Verständnis der objektorientierten Programmierung an sich und der verwendeten Klassen im Besonderen. Der damit verbundene Lernaufwand ist aber eine unverzichtbare Voraussetzung, wenn man sich der vielfältigen Möglichkeiten der .NET-Welt in COBOL-Programmen bedienen will.
Zum Glück ist das moderne COBOL nicht mehr jenes COBOL, das zu lernen .NET-Anhänger sich einst geweigert hatten. Mit dem neuen, im Jahre 2002 verabschiedeten ISO-COBOL-Standard haben objektorientierte Konzepte erstmals auch offiziell Eingang in die klassische COBOL-Syntax gefunden. Sie erlauben nun die Verwendung von Klassen und deren Methoden in einem prozeduralen COBOL-Programm sowie die Definition von Klassen in COBOL selbst.
Wie das genau funktioniert, lässt sich am einfachsten mit einigen konkreten Beispielen zeigen; sie sind einem COBOL-Programm entnommen, das Methoden der .NET-Framework-Klassen benutzt. Die verwendeten Klassen müssen zunächst im COBOL-Programm im Repository-Paragraphen referenziert werden:
REPOSITORY.
CLASS StringClass As "System.String"
Damit wird die zu verwendende Klasse benannt und mit einem programminternen Namen verknüpft. Die nächste Anweisung:
01 numberString OBJECT REFERENCE StringClass.
legt ein Datenelement vom Typ "OBJECT REFERENCE" an, mit dem die Objekte und Methoden der jeweiligen Klasse angesprochen werden können. Dabei wird die Klasse festgelegt, auf die mit dieser Object Reference zugegriffen werden kann.
Mit der COBOL-Anweisung "INVOKE" können Methoden von Klassen aufgerufen werden. Im folgenden Beispiel wird die Methode "ToString" aus einer anderen Klasse aufgerufen, die eine Referenz auf ein Objekt der Klasse "StringClass" zurückliefert:
INVOKE ConvertClass "ToString" USING
BY VALUE numberValue
RETURNING numberString
Jetzt kann auf das durch "numberString" referenzierte Objekt der StringClass zugegriffen werden, um den enthaltenen String in eine TextBox der Winforms-Klasse zu übertragen, die dann in einem Fenster auf dem Bildschirm zur Anzeige gebracht werden kann.
SET TextProperty OF onHandNumber TO numberString
Dem klassischen COBOL-Programmierer ist diese Art der Syntax zwar vertraut, erfordert aber das Verständnis der objektorientierten Programmierung an sich und der verwendeten Klassen im Besonderen. Der damit verbundene Lernaufwand ist aber eine unverzichtbare Voraussetzung, wenn man sich der vielfältigen Möglichkeiten der .NET-Welt in COBOL-Programmen bedienen will.
Bitte einpacken
Dazu zählt beispielsweise die Bereitstellung von bestehendem COBOL-Code für den Aufruf in .NET-Applikationen, sofern die aufrufenden Programme selbst nicht in COBOL geschrieben sind. Von COBOL zu COBOL gibt es auch in der .NET-Umgebung die Abkürzung über das klassische "CALL", mit dem ein COBOL-Programm ein anderes aufrufen kann. Ist das aufrufende Programm jedoch nicht in COBOL geschrieben, sondern zum Beispiel in C# oder VB.NET und damit objektorientiert, so muss das aufzurufende COBOL-Programm zunächst eine objektorientierte Schale bekommen, ein sogenanntes Wrapping. Erst wenn diese Schale vorhanden ist, kann das COBOL-Programm von einer reinen OO-Sprache aufgerufen werden. Dieses Wrapping wird im folgenden Beispiel erläutert.
Im CLASS-ID Paragraphen wird zunächst der Name der Klasse festgelegt:
CLASS-ID. "BookHandler".
In der PROCEDURE DIVISION befindet sich in einem COBOL-Programm das Coding. Das ist die Stelle, an der die Methoden der Klasse definiert werden:
PROCEDURE DIVISION.
METHOD-ID. CallBookProgram As "CallBookProgram".
Die einzelnen Methoden können lokale Daten enthalten, die beim jeweiligen Aufruf der Methode als methodenspezifischer Speicherbereich zur Verfügung stehen. Definiert werden diese Daten in der WORKING-STORAGE SECTION innerhalb der Methode:
WORKING-STORAGE SECTION.
01 ws-book-details.
03 ws-book-text-details.
05 ws-book-title pic x(50).
05 ws-book-type pic x(20).
05 ws-book-author pic x(50).
Im Gegensatz dazu beschreibt die LINKAGE SECTION die an den Methodenaufruf übergebenen Parameter, die aus der objektorientierten Welt als Objektreferenzen geliefert werden:
LINKAGE SECTION.
01 bookTitle OBJECT REFERENCE TextBoxClass.
01 bookAuthor OBJECT REFERENCE TextBoxClass.
Danach beginnt der methodenspezifische Code mit einem neuerlichen PROCEDURE DIVISION Header, in dem die übergebenen Parameter aufgelistet werden:
PROCEDURE DIVISION USING BY VALUE bookFunction
BY VALUE bookTitle
BY VALUE bookAuthor.
Aus den übergebenen Objekten müssen nun noch die Informationen in die lokalen Datenfelder übertragen werden:
SET ws-book-title TO TextProperty OF bookTitle
Diese lokalen Datenfelder entsprechen in ihrem Datentyp und ihrer Länge den Daten, die das prozedurale COBOL-Programm erwartet und können jetzt mit dem klassischen COBOL-CALL an das aufzurufende COBOL-Programm übergeben werden:
CALL "BOOK" USING ws-function
ws-book-details
ws-file-status.
Danach müssen die als Parameter zurückgegebenen Dateninhalte wieder in die Objekte der Methodenschnittstelle übertragen werden:
SET TextProperty OF bookAuthor TO ws-book-author
Damit schliesst sich die Lücke zwischen dem klassischen, prozeduralen COBOL-Programm und der objektorientierten .NET-Welt. Die hier beschriebene COBOL-Wrapper-Klasse kann wie jede andere Klasse in der .NET-Welt angesprochen werden, und zwar von jeder .NET-Sprache aus.
Für das Deployment ist eines zu beachten: Neben der Laufzeitumgebung des .NET Framework, die im Redistributable Package zur Verfügung gestellt wird und die die CLR und andere Komponenten für das .NET Framework enthält, benötigen COBOL-basierte .NET-Anwendungen eine zusätzliche COBOL-Laufzeitumgebung. Sie übernimmt die Abbildung der nicht .NET-sprachspezifischen Funktionen, zum Beispiel das COBOL-Dateihandling. Diese COBOL Runtime Engine stellt der Application Server bereit, der in Micro Focus' Net Express with .NET ebenfalls enthalten ist.
Im CLASS-ID Paragraphen wird zunächst der Name der Klasse festgelegt:
CLASS-ID. "BookHandler".
In der PROCEDURE DIVISION befindet sich in einem COBOL-Programm das Coding. Das ist die Stelle, an der die Methoden der Klasse definiert werden:
PROCEDURE DIVISION.
METHOD-ID. CallBookProgram As "CallBookProgram".
Die einzelnen Methoden können lokale Daten enthalten, die beim jeweiligen Aufruf der Methode als methodenspezifischer Speicherbereich zur Verfügung stehen. Definiert werden diese Daten in der WORKING-STORAGE SECTION innerhalb der Methode:
WORKING-STORAGE SECTION.
01 ws-book-details.
03 ws-book-text-details.
05 ws-book-title pic x(50).
05 ws-book-type pic x(20).
05 ws-book-author pic x(50).
Im Gegensatz dazu beschreibt die LINKAGE SECTION die an den Methodenaufruf übergebenen Parameter, die aus der objektorientierten Welt als Objektreferenzen geliefert werden:
LINKAGE SECTION.
01 bookTitle OBJECT REFERENCE TextBoxClass.
01 bookAuthor OBJECT REFERENCE TextBoxClass.
Danach beginnt der methodenspezifische Code mit einem neuerlichen PROCEDURE DIVISION Header, in dem die übergebenen Parameter aufgelistet werden:
PROCEDURE DIVISION USING BY VALUE bookFunction
BY VALUE bookTitle
BY VALUE bookAuthor.
Aus den übergebenen Objekten müssen nun noch die Informationen in die lokalen Datenfelder übertragen werden:
SET ws-book-title TO TextProperty OF bookTitle
Diese lokalen Datenfelder entsprechen in ihrem Datentyp und ihrer Länge den Daten, die das prozedurale COBOL-Programm erwartet und können jetzt mit dem klassischen COBOL-CALL an das aufzurufende COBOL-Programm übergeben werden:
CALL "BOOK" USING ws-function
ws-book-details
ws-file-status.
Danach müssen die als Parameter zurückgegebenen Dateninhalte wieder in die Objekte der Methodenschnittstelle übertragen werden:
SET TextProperty OF bookAuthor TO ws-book-author
Damit schliesst sich die Lücke zwischen dem klassischen, prozeduralen COBOL-Programm und der objektorientierten .NET-Welt. Die hier beschriebene COBOL-Wrapper-Klasse kann wie jede andere Klasse in der .NET-Welt angesprochen werden, und zwar von jeder .NET-Sprache aus.
Im linken Fenster ist die in OO-COBOL codierte Source BOOKHANDLER geöffnet, die die Zugriffe auf die .Net-Klassen enthält.
Für das Deployment ist eines zu beachten: Neben der Laufzeitumgebung des .NET Framework, die im Redistributable Package zur Verfügung gestellt wird und die die CLR und andere Komponenten für das .NET Framework enthält, benötigen COBOL-basierte .NET-Anwendungen eine zusätzliche COBOL-Laufzeitumgebung. Sie übernimmt die Abbildung der nicht .NET-sprachspezifischen Funktionen, zum Beispiel das COBOL-Dateihandling. Diese COBOL Runtime Engine stellt der Application Server bereit, der in Micro Focus' Net Express with .NET ebenfalls enthalten ist.
Kulturschock
So nützlich und sinnvoll eine Verbindung von .NET und COBOL ohne Zweifel ist, sie ist in der Praxis für beide Seiten gewöhnungsbedürftig - nicht zuletzt, weil sich hier nicht nur zwei unterschiedliche Software-Konzepte gegenüberstehen, sondern auch zwei Welten der Softwareentwicklung, die sich lange aus dem Weg gegangen sind, aufeinander stoßen. So konfrontiert Micro Focus' Net Express den klassischen COBOL-Programmierer, der sich bisher zumindest beim Entwickeln auf dem Mainframe bewegt hat, mit einem regelrechten Kulturschock, wenn das vertraute Entwicklungswerkzeug nun auf einmal ganz in Visual Studio .NET integriert ist. Hat sich der erste Schock gelegt, darf der Entwickler die Vorteile und den Komfort von Visual Studio .NET umso unbeschwerter genießen. Unterdessen können .NET-Entwickler darüber staunen, wie nahtlos sich eine Sprache, die ursprünglich ganz anders konzeptioniert war, in .NET einfügt.