Zeitgleich mit RPG IV wurden auch die ILE-Konzepte eingeführt, nach denen in und mit RPG, aber auch mit anderen (ILE-)Programmiersprachen, wie zum Beispiel Cobol, CL oder C, programmiert werden kann.

Da RPGIV und die ILE-Konzepte zur gleichen Zeit eingeführt wurden und RPGIV-Quellcode mit dem ILE-Compiler umgewandelt wird, werden RPGIV und ILERPG im Sprachgebrauch oft als Synonym verwendet, was jedoch von der Sache her nicht korrekt ist. Viele RPG-Programmierer schreiben auch heute noch ihre Programme „nur“ in modernem RPGIV. Auch die Verwendung der letzten Erweiterungen in RPG – wie etwa qualifizierte und verschachtelte Datenstrukturen, Built-in-Funktionen, Free-Format-Codierung oder XML-Verarbeitung –, macht aus RPGIV noch kein ILERPG. Erst durch den Einsatz von ILE-Konzepten wird aus RPGIV ILERPG.

Was verbirgt sich hinter dem Mysterium ILE?

ILE steht für Integrated Language Environment und war ursprünglich dazu gedacht, Prozeduren, Funktionen und Methoden, die in anderen Programmiersprachen geschrieben wurden, aus den ILE-Sprachen (zum Beispiel RPG, CL oder COBOL heraus aufzurufen. Während im klassischen RPG sowie in COBOL und CL der Source Code in Programme umgewandelt wird, die über entsprechende CALL-Befehle aufgerufen und ausgeführt werden, gibt und gab es auch schon früher in anderen Sprachen noch weitere ausführbare Konstrukte, z.B. Prozeduren und Funktionen.

In RPGIII bestand keine Möglichkeit, solche Konstrukte zu verwenden. Mit Hilfe der ILE-Konzepte können Prozeduren und Funktionen, die in anderen Programmiersprachen geschrieben wurden, direkt aus den ILE-Sprachen heraus aufgerufen und ausgeführt werden. Mit Hilfe der ILE-Konzepte ist es auch möglich, mit ILE-Sprachen solche Prozeduren und Funktionen zu erzeugen.

Des Weiteren erlauben die ILE-Konzepte, Programme aus mehreren Programmteilen zu bilden. Diese Programmteile wiederum können in unterschiedlichen Programmiersprachen verfasst worden sein. Der Grundgedanke von ILE ist: Verwende die Programmiersprache, die für die aktuelle Aufgabe am besten geeignet ist.

Warum sollte man ILE-Konzepte verwenden?

Hier einige der häufigsten Begründungen, warum ILE-Konzepte nicht verwendet werden und warum man sie trotzdem einsetzen sollte.

  • Wir beherrschen sowieso nur eine Programmiersprache und Programme in RPG oder CL können über CALL-Befehle aufgerufen werden? ILE-Konzepte erlauben eine hochmodulare Programmierung, in der wiederverwendbarer Code separiert wird und – wo immer er benötigt wird – integriert werden kann. Große Programme werden dazu in gekapselte Einzelteile (Prozeduren=“Mini-Progrämmchen“) aufgesplittet, die wiederverwendbaren Code beinhalten.
  • Ja! Aber das machen wir doch heute auch, wir teilen Programme in Subroutinen auf, die mehrfach aufgerufen werden! Was aber, wenn die gleiche Subroutine in mehreren Programmen verwendet werden muss?
  • Dann kopieren wir die Subroutine oder legen den Source Code in eine Copy-Strecke und integrieren diese, oder wir generieren ein Unterprogramm. Wird Source Code kopiert, so muss im Falle einer Änderung diese in allen Duplikaten gemacht werden, was zum einen mehrfachen Zeitaufwand bedeutet. Zum anderen ist es schwierig, jeweils alle Duplikate zu finden.
  • Bei der Verwendung von Copy-Strecken muss der Source Code zwar nur einmal gewartet werden, Copy-Strecken sind jedoch nicht gekapselt. In den Copy-Strecken kann und muss auf globale Variablen, die außerhalb der Copy-Strecke definiert wurden zugegriffen werden. Setzt man Copy-Strecken ein, so muss sichergestellt werden, dass innerhalb der Copy-Strecken nicht versehentlich solche globalen Variablen verändert werden, denn das kann zu unerwarteten Ergebnissen führen.

Wird eine Copy-Strecke geändert, müssen alle Teildateien, in die die Copy-Strecke eingebunden wurde, neu kompiliert werden. Jedes neu erstelle Programm muss einzeln getestet werden, um sicherzustellen, dass die Änderung korrekt funktioniert.

Erstellt man anstatt einer Subroutine ein Programm, so muss der Source Code nur einmal gewartet werden, außerdem können Daten nur über Parameter ausgetauscht werden. Bei einer Änderung, muss lediglich das Unter-Programm neu erstellt werden.

Der dynamische Aufruf von Programmen erzeugt jedoch einen Overhead, das heißt, Speicher muss reserviert und initialisiert werden, Dateien müssen geöffnet werden etc., was beim Einsatz von vielen Unter-Programmen einen negativen Einfluss auf die Laufzeit haben kann.

Da für den Source Code eines Programms außerdem jeweils eine eigene Teildatei verwendet wird, und ein Programm-Name aus maximal 10 Zeichen bestehen kann, hält sich die Anzahl der Unterprogramme allein schon aufgrund der Namensrestriktion in Grenzen. So wird man selten Unterprogramme finden, die aus zehn oder noch weniger Code-Zeilen bestehen.

Kapselt man stattdessen die Subroutine in eine Prozedur, kann man diese wie ein Programm über entsprechende CALL-Prozedur-Befehle aufrufen. Prozeduren sind kleine Blackboxen, in denen bestimmte Aufgaben ausgeführt werden. Der Austausch von Daten erfolgt idealerweise nur über Parameter.

Im Gegensatz zu Programm-Namen, die 10 Zeichen nicht überschreiten dürfen, können Prozedur-Namen, zumindest in RPG, bis 4.096 Zeichen lang sein. Dem Einsatz von langen, sprechenden Namen steht somit nichts im Wege.

Mehrere Prozeduren können in einer Teildatei (unabhängig vom Programmcode) zusammengefasst, exportiert und individuell aufgerufen werden. Die Teildateien werden in Module kompiliert und anschließend entweder in Programme oder Serviceprogramme eingebunden.

Prozeduren können im Programmcode als interne Prozeduren hinterlegt und somit als „Programm im Programm“ angesehen werden. Prozeduren können jedoch auch exportiert werden. Exportierte Prozeduren können aus anderen Programmen oder von Prozeduren im gleichen oder einem anderen Service-Programm heraus aufgerufen werden.

Da Module in Programme und/oder Service-Programme gebunden werden, werden sie Bestandteil des (Service-)Programm-Objekts. Beim Aufruf von Prozeduren entfällt der Aktivierungsaufwand der beim Aufruf von Unter-Programmen entsteht. Prozeduren, auch wenn sie außerhalb des Programms codiert und in Service-Programmen gebunden wurden, werden zur Laufzeit fast genauso schnell verarbeitet wie Subroutinen.

Prozeduren können und sollten nach Funktionalität in Teildateien zusammengefasst und sofern immer möglich exportiert werden. Ein Beispiel: Alle Prozeduren für die Datums- und Zeitrechnung werden in einer Teildatei gesammelt, in einer anderen Teildatei sind alle String-Handling-Prozeduren enthalten und in einer dritten Teildatei sind alle Prozeduren hinterlegt, in denen auf eine bestimmte Datei/Tabelle zugriffen wird.

Benötigt der Programmierer eine Datumsroutine, so schaut er in die Teildatei, in der die Datumsroutinen hinterlegt sind. Findet er die Routine, die er benötigt, ruft er sie auf. Findet er keine entsprechende Prozedur, fügt er eine neue exportierte Prozedur mit der entsprechenden Funktionalität hinzu. Der nächste Programmierer, der die gleiche Routine benötigt, kann diese neue Prozedur dann ebenfalls einsetzen.

Das Schöne an Prozeduren ist, dass sie einzeln codiert und direkt aufgerufen und getestet werden können; im Gegensatz zu Subroutinen, die nur innerhalb eines Programms oder einer Prozedur ausgeführt werden können.

Bei näherer Beschäftigung mit den ILE-Konzepten, wird man feststellen, dass sich die  Programmier-Richtung geändert hat. Klassische Programme wurden – auch bedingt durch den RPG-Zyklus – Top-down, also von oben nach unten codiert. Mit ILE geht man in der umgekehrten Richtung vor, das heißt, zunächst plant und designt man die einzelnen Prozeduren, und erst zum Schluss setzt man sie zu einem Programm zusammen.

Das Schwierigste beim Einsatz der ILE-Konzepte ist die modulare Denkweise, das heißt, der klassische RPG- und Cobol-Programmierer muss zuerst lernen, modular zu denken. Das geht nicht von heute auf morgen, sondern ist ein fortlaufender Prozess. Bei den ersten Versuchen werden die Prozeduren von der Größe her eher an Programme erinnern. Mit der Zeit jedoch werden die Prozeduren immer überschaubarer.

In einer echten ILE-Umgebung wird es nur noch kleine Programme und sehr viele noch kleinere Prozeduren geben. Aus den Programmen und Prozeduren werden weitere Prozeduren aufgerufen und ausgeführt. Nur wenige Prozeduren werden mehr als 50–100 Codezeilen enthalten.

Anwendungsmodernisierung mit ILE-Konzepten

Mit Hilfe der ILE-Konzepte ist es möglich, selbst alte, gewachsene Software zu modernisieren. Das Programmiererteam sollte sich dazu zunächst zusammensetzen und festlegen, welche Prozeduren benötigt und daher erstellt werden sollten. Für den Einstieg fängt man mit kleinen allgemein wiederverwendbaren Prozeduren an, zum Beispiel mit Datumsroutinen und String-Handling-Funktionen.

Bei den anwendungsspezifischen Prozeduren beginnt man zunächst mit den Prozeduren für die Eingabeprüfungen. Beispiele dafür sind „StatusErfasst“, „StatusGültig“ etc. Was die sonstigen anwendungsindividuellen Prozeduren angeht, so nimmt man sich zuerst die Subroutinen vor, von denen man weiß, dass sie in mehreren Programmen codiert wurden.

Die neuen Prozeduren sollten nach Funktionalität und nicht nach Programmzugehörigkeit gruppiert werden. So sollten alle Datumsroutinen in einem Modul oder Service-Programm zusammengruppiert werden. Alle String-Handling-Funktionen werden in einem anderen Modul oder Service-Programm konzentriert. Alle Zugriffe auf den Artikel-Stamm werden in einem weiteren Modul oder Service-Programm eingebunden … usw.

Prozedurnamen sind im Gegensatz zu Programmnamen nicht auf zehn Zeichen beschränkt. Deshalb können und sollten kryptische Namen wie zum Beispiel AY123#FA, vermieden und stattdessen sprechende Namen verwendet werden. Da jedoch voraussichtlich eine Vielzahl von Prozeduren erstellt werden wird, sollte man vorab Namenskonventionen festlegen. Zum einen können dadurch doppelte Prozeduren vermieden werden, zum anderen können durch saubere Namenskonventionen vorhandene Prozeduren von allen Programmierern leichter lokalisiert werden.

Die Verwendung von sprechenden Prozedurnamen hat noch einen kleinen, jedoch nicht zu unterschätzenden Nebeneffekt. Man erreicht nämlich eine „Dokumentation durch Codierung“, so dass selbst ein fremder Programmierer den Quelltext überblicken kann, auch wenn keine (weiteren) Kommentare im Quellcode hinterlegt sind, wie das Beispiel in Listing 1. zeigt.

Quelle: Birgitta Hauser

Listing 1. Dokumentation durch Codierung

Wiederverwendbare Prozeduren können designt, codiert, umgewandelt und getestet werden, ohne die vorhandenen Programme ändern zu müssen. Da es sich bei den wiederverwendbaren Prozeduren um „Mini-Programme“ handelt, ist es möglich, immer mal wieder eine Prozedur „so nebenher“ zu erstellen und zu testen. Neue Prozeduren müssen nicht immer sofort in alle Programme eingebunden werden, auch wenn dies wünschenswert wäre. Es genügt die Änderungen nach und nach vorzunehmen.

Sofern man die Anwendungsmodernisierung ernsthaft vorantreiben will, sollte man den Fokus zunächst darauflegen, Prozeduren, die häufig eingesetzt werden können zu planen, erstellen und testen. Im Anschluss daran können diese Prozeduren in dem vorhandenen Quell-Code integriert werden. Im Hinblick darauf sollte man auch die noch verbliebenen RPG-III-Programme mit Hilfe des CL-Befehls CVTRPGSRC (RPG-Quellen konvertieren) nach RPG IV portieren. Die Konvertierung sollte zumindest dann erfolgen, wenn man nicht umhinkommt, ein solch altes Programm zu modifizieren.

Wann immer ein nach RPGIV konvertiertes Programm modifiziert werden muss, können in diesem Programm vorhandene Subroutinen oder auch einzelne Codezeilen durch einen Aufruf von neuen, getesteten Prozeduren ersetzt werden. Auf diese Weise wird der alte Source Code nach und nach durch Prozeduraufrufe ersetzt, was den ursprünglichen Quellcode in der Regel beträchtlich reduziert und wesentlich übersichtlicher macht.

Irgendwann in der Zukunft werden alle Programme modernisiert, strukturiert und wieder einfach zu warten sein, was mit Sicherheit besser ist, als irgendeine neue (Standard-)Software zu kaufen, die nur zum Teil den Anforderungen und vorhandenen Abläufen entspricht.

Soweit zum Überblick, was sich hinter den ILE-Konzepten verbirgt. In einer Reihe von weiteren Artikeln, wird Step by Step gezeigt, wie man von monolithischen Programmen, vorhandenen Copy-Strecken und Sub-Routinen über gebundene Module, interne und exportierte Prozeduren und Service-Programmen zu einem modulare Programm-Design kommt. Und jetzt schon einmal viel Spaß bei der Überlegung, wie ILE Konzepte im eigenen Betrieb umgesetzt werden könnten.

Birgitta Hauser