Paradigmen und Programmierkonzepte: RPG und Java im Vergleich

tiny-tool.de

tiny-tool.de

Die Wahl zwischen IBM RPG (fully free) und Java stellt Entwickler vor die Frage, welches Paradigma ihren Anforderungen besser entspricht. Während RPG tief mit der IBM i-Plattform verwurzelt ist, bietet Java universelle Flexibilität. Dieser Artikel beleuchtet drei zentrale Aspekte: prozedurale vs. objektorientierte Ansätze, strukturelle Unterschiede und die Fehlerbehandlung.

Prozedurale vs. objektorientierte Ansätze

RPG folgt traditionell einem prozeduralen Ansatz, bei dem zentrale Variablen direkt manipuliert werden. Im Vergleich dazu setzt Java auf Objektorientierung, bei der Daten und Funktionen in Klassen kapsuliert sind. Diese grundlegenden Unterschiede zeigen sich bereits in einfachen Beispielen wie der Verwaltung eines Bankkontos.

Praxisbeispiele

RPG-Code:

Im gezeigten Beispiel wird der Kontostand in einer globalen Variable balance gespeichert, die direkt von den Prozeduren DEPOSIT und WITHDRAW manipuliert wird. Dieses Vorgehen war in der Vergangenheit weit verbreitet und findet sich auch heute noch häufig in RPG-Code – selbst in der modernen „fully free“-Variante.

Der gezeigte Ansatz verdeutlicht, wie direkter Zugriff auf globale Variablen die Kapselung untergräbt und zu unerwarteten Seiteneffekten führen kann. Statt Rückgabewerte von Prozeduren zu verwenden oder Variablen gezielt zu kapseln, wird hier die zentrale Variable direkt verändert. Der Code dient somit als Beispiel für eine Praxis, die in modernen Programmieransätzen vermieden werden sollte.

RPG DCL-S balance PACKED(7:2) INZ(0); // Speichert den aktuellen Kontostand P DEPOSIT B   DCL-PI *N;     amount PACKED(7:2);   END-PI;   // Fügt den Betrag zum Kontostand hinzu   balance += amount; // Globaler Wert wird direkt geändert. Vermeiden! P DEPOSIT E P WITHDRAW B   DCL-PI *N;     amount PACKED(7:2);   END-PI;   // Zieht den Betrag vom Kontostand ab   balance -= amount; // Globaler Wert wird direkt geändert. Vermeiden! P WITHDRAW E // Prozeduraufrufe DEPOSIT(100.00); // 100 hinzufügen WITHDRAW(50.00); // 50 abheben // Kontostand anzeigen DSPLY 'Aktueller Kontostand: ' + balance; // Gibt den aktuellen Kontostand aus

Dieser Ansatz ist kompakt, birgt jedoch das Risiko von Seiteneffekten, da balance von überall aus geändert werden kann.

Verbesserter RPG-Ansatz:

Moderneres RPG setzt auf Kapselung, um die Datenintegrität zu schützen. Der Zugriff auf balance erfolgt nur über Service-Prozeduren wie GETBALANCE und DEPOSIT:

RPG DCL-S balance PACKED(7:2) INZ(0); // Speichert den aktuellen Kontostand P DEPOSIT B   DCL-PI PACKED(7:2);     amount PACKED(7:2);   END-PI;   RETURN balance + amount; // Fügt den Betrag zum Kontostand hinzu P DEPOSIT E P WITHDRAW B   DCL-PI PACKED(7:2);     amount PACKED(7:2);   END-PI;   RETURN balance - amount; // Zieht den Betrag vom Kontostand ab P WITHDRAW E P GETBALANCE B   DCL-PI PACKED(7:2);   END-PI;   RETURN balance; // Gibt den aktuellen Kontostand zurück P GETBALANCE E // Prozeduraufrufe balance = DEPOSIT(100.00); // 100 einzahlen balance = WITHDRAW(50.00); // 50 abheben balance = GETBALANCE(); // Kontostand abfragen DSPLY 'Aktueller Kontostand: ' + balance; // Gibt den aktuellen Kontostand aus

Die globale Variable wird durch Kapselung vor direktem Zugriff geschützt, was die Integrität der Daten sicherstellt. Anstatt die balance-Variable überall im Code direkt zu manipulieren, wird der Zugriff über klar definierte Prozeduren geregelt. Das erhöht die Wartbarkeit des Codes, da Änderungen an der Implementierung der Prozeduren keinen Einfluss auf andere Teile des Programms haben. Zudem wird das Risiko von Seiteneffekten minimiert, da die Variable nicht versehentlich von anderen Prozeduren oder Funktionen verändert wird.

Java-Code:

In Java wird derselbe Fall durch eine Klasse BankAccount umgesetzt. Die zentrale Idee hinter der Kapselung besteht darin, Daten vor unkontrolliertem Zugriff zu schützen und nur über definierte Schnittstellen – in diesem Fall öffentliche Methoden – zu manipulieren. Die Felder der Klasse sind privat, was verhindert, dass andere Klassen oder Objekte direkten Zugriff auf die Variablen erhalten.

Dieser Ansatz bietet mehrere Vorteile:

  • Datenintegrität: Der Kontostand (balance) kann nur über kontrollierte Methoden wie deposit oder withdraw verändert werden.
  • Erweiterbarkeit: Änderungen an der Implementierung, z. B. das Hinzufügen neuer Regeln oder Berechnungen, können vorgenommen werden, ohne den Aufrufercode zu beeinflussen.
  • Lesbarkeit und Wartbarkeit: Der Code bleibt modular und gut verständlich, da die Logik zur Manipulation der Daten zentral in der Klasse gekapselt ist.
Java public class BankAccount {     private double balance; // Speichert den aktuellen Kontostand     public double deposit(double amount) { // Fügt den Betrag zum Kontostand hinzu         this.balance += amount; // Aktualisiert den Kontostand         return this.balance; // Gibt den neuen Kontostand zurück     }     public double withdraw(double amount) { // Zieht den Betrag vom Kontostand ab         this.balance -= amount; // Aktualisiert den Kontostand         return this.balance; // Gibt den neuen Kontostand zurück     }     public double getBalance() { // Gibt den aktuellen Kontostand zurück         return this.balance;     } } public class Main {     public static void main(String[] args) {         BankAccount account = new BankAccount(); // Erstellt ein neues Konto         account.deposit(200.00); // 200 einzahlen         account.withdraw(50.00); // 50 abheben         double currentBalance = account.getBalance(); // Aktuellen Kontostand abrufen         System.out.println("Aktueller Kontostand: " + currentBalance); // Ausgabe des Kontostands     } }

Diese Struktur schützt vor unkontrollierten Zugriffen und ist einfacher zu erweitern.

Strukturelle Unterschiede

Die Organisation von Code unterscheidet sich in RPG und Java grundlegend. RPG folgt einem prozeduralen Aufbau, der auf unabhängigen Source-Membern basiert, während Java auf einer hierarchischen, objektorientierten Struktur mit Paketen und Klassen aufbaut.

Organisation des Codes

RPG:

In RPG werden Source-Member in sogenannten Source-Dateien organisiert. Jedes Member ist eine eigenständige Einheit und kann Prozeduren, Subroutinen oder Datenstrukturen enthalten:

  • Prozeduren: Logische Operationen werden in klar abgegrenzten Blöcken implementiert.
  • Subroutinen: Kleinere, wiederverwendbare Codeabschnitte innerhalb eines Members.
  • Datenstrukturen und Variablen: Globale oder lokale Datenfelder, die innerhalb des Members genutzt werden.

Ein Beispiel für eine typische RPG-Organisation:

Source-Datei: BANKSRC
Member: DEPOSIT (Prozedur für Einzahlungen)
Member: WITHDRAW (Prozedur für Abhebungen)
Member: BALANCE (Variable für Kontostand)

Java:

Java organisiert Code in einer klaren Hierarchie aus Paketen, Klassen und Methoden. Diese Struktur fördert Modularität und Wiederverwendbarkeit:

  • Pakete: Gruppieren verwandte Klassen (z. B. com.bank).
  • Klassen: Definieren Daten und Verhalten für ein spezifisches Konzept (z. B. BankAccount).
  • Methoden: Enthalten die Logik für spezifische Operationen (z. B. deposit()).

Ein Beispiel für eine typische Java-Organisation:

Paket: com.bank
Klasse: BankAccount
Feld: balance (Kontostand)
Methode: deposit (Einzahlungen)
Methode: withdraw (Abhebungen)

Aufbau eines Programms

RPG:

  • Kontrollspezifikationen
  • Dateispezifikationen
  • Datenbeschreibungen
  • Prozeduren

Java:

  • Paket- und Import-Anweisungen
  • Klassen- und Schnittstellendefinitionen
  • Felder und Konstruktoren
  • Methoden

Vergleich der Ansätze zur Fehlerbehandlung

RPG: In RPG werden Fehler direkt in der Prozedur behandelt, in der sie auftreten. Dies erfolgt meist durch Kontrollstrukturen wie MONITOR und ON-ERROR. Sobald ein Fehler erkannt wird, kann die Prozedur darauf reagieren, ohne dass der Fehler explizit weitergegeben werden muss.

Dieser Ansatz hat Vor- und Nachteile:

  • Vorteile:
    • Die Fehlerbehandlung ist lokal und einfach. Jede Prozedur ist dafür verantwortlich, ihre eigenen Fehler zu handhaben.
    • Die Implementierung ist übersichtlich, da keine zusätzlichen Mechanismen wie das Weiterreichen von Fehlern erforderlich sind.
  • Nachteile:
    • Die Fehlerbehandlung bleibt auf die jeweilige Prozedur beschränkt. Das bedeutet, dass Fehler nicht von einer übergeordneten Prozedur oder einem anderen Kontext behandelt werden können.
    • Es erschwert die Wiederverwendbarkeit und Modularität, da jede Prozedur ihre eigene Fehlerlogik implementieren muss.

Ein typisches Beispiel:

MONITOR;   fileHandle = OPEN(''/path/to/file'': ''O''); // Versucht die Datei zu öffnen ON-ERROR;   DSPLY 'Fehler beim Öffnen der Datei'; // Gibt eine Fehlermeldung aus ENDMON;

Hier wird der Fehler direkt in der gleichen Prozedur abgefangen, in der er auftritt. Es gibt keine Möglichkeit, diesen Fehler an einen anderen Teil des Programms weiterzugeben.

Java: In Java erfolgt die Fehlerbehandlung über ein flexibles Exception-Handling-System. Fehler werden als Exceptions geworfen (throw) und können entlang der Aufrufkette an die aufrufende Methode oder eine zentrale Fehlerbehandlungsroutine weitergegeben werden. Dies ermöglicht eine strukturierte und modulare Fehlerbehandlung.

Ein Beispiel für die Weitergabe von Fehlern:

public void readFile(String filePaththrows FileNotFoundException {
    File file = new File(filePath); // Erstellt ein File-Objekt
    Scanner scanner = new Scanner(file); // Öffnet die Datei zum Lesen
    while (scanner.hasNextLine()) {
        System.out.println(scanner.nextLine()); // Gibt die nächste Zeile aus
    }
    scanner.close(); // Schließt den Scanner
}

Hier ist die readFile-Methode nicht dafür verantwortlich, den Fehler zu behandeln, wenn die Datei nicht gefunden wird. Die Methode könnte auch selbst den Fehler behandeln, ähnlich wie es in RPG der Fall ist, jedoch wirft sie die Exception weiter, damit der Fehler von einer anderen Methode behandelt werden kann. Dadurch entsteht mehr Flexibilität:

  • Vorteile:
    • Fehler können auf unterschiedlichen Ebenen behandelt werden, z. B. zentral in einer „Controller“-Schicht.
    • Der Code bleibt modularer, da Methoden nicht mit überflüssiger Fehlerlogik überladen werden müssen.
    • Java erlaubt es, verschiedene Arten von Fehlern gezielt zu behandeln, indem spezifische Exception-Klassen verwendet werden (FileNotFoundException, IOException, etc.).
  • Nachteile:
    • Es ist oft mehr Aufwand erforderlich, da die Fehler entweder weitergegeben oder auf verschiedenen Ebenen behandelt werden müssen.
    • Entwickler müssen sicherstellen, dass wichtige Fehler nicht unbehandelt bleiben.

Vergleich der Ansätze

  • Direkte Behandlung des Errors (RPG): Einfach und lokal, aber weniger flexibel.
  • Weitergeben der Exception (Java): Flexibler und modularer, ermöglicht zentralisierte Fehlerbehandlung.

Schlusswort

Die Wahl zwischen RPG und Java hängt stark von den Anforderungen und der Umgebung des jeweiligen Projekts ab. RPG überzeugt mit seiner engen Integration in die IBM i-Plattform und bietet durch seinen prozeduralen Ansatz eine schnelle und einfache Implementierung, insbesondere für kleinere Anwendungen mit klar definierten Aufgaben. Java hingegen punktet durch seine universelle Einsetzbarkeit, seine objektorientierten Prinzipien und die dadurch entstehende Modularität und Wiederverwendbarkeit.

Die aufgezeigten Unterschiede – von der Datenkapselung über die Organisation des Codes bis hin zur Fehlerbehandlung – zeigen, dass beide Sprachen unterschiedliche Philosophien verfolgen, um Herausforderungen in der Softwareentwicklung zu lösen. Während RPG traditionell auf Effizienz und Pragmatismus setzt, bietet Java durch seine Flexibilität eine größere Bandbreite an Möglichkeiten für komplexe, skalierbare Systeme.

Am Ende ergänzen sich beide Ansätze: Die Stärken von RPG in der Verwaltung von Datenströmen und Geschäftslogik auf IBM-Systemen sind unübertroffen, während Java als vielseitige Programmiersprache in nahezu allen modernen Softwareprojekten glänzen kann. Ein Verständnis beider Sprachen und Paradigmen hilft dabei, die besten Werkzeuge für jede Aufgabe zu wählen und voneinander zu lernen.

Ob du nun tief in der RPG-Welt verwurzelt bist oder mit Java die nächste große Anwendung entwickeln möchtest, eins bleibt sicher: Der Schlüssel liegt darin, die Stärken der jeweiligen Sprache zu nutzen und sie kreativ für die eigenen Anforderungen zu nutzen. 🚀

Dieser Artikel bietet einen kompakten Überblick über die Unterschiede zwischen RPG und Java und dient als Einstieg in die beiden Programmierwelten. Für eine tiefere Auseinandersetzung und weiterführende Informationen empfehlen wir die folgenden Ressourcen: