Insane in the mainframe?

Irina Siebrand & Matthias Voss  /  02.11.21  /  Managed Services

 

Ich entwickle jetzt auf dem Großrechner in COBOL. Pause. Ein Blick meiner Kommilitonin verrät mir, dass sie denkt: „Verrückt, wer macht denn sowas heutzutage“.

In der Tat ist COBOL inzwischen über 60 Jahre alt:  COBOL steht für „Common Business Oriented Language“ und ist eine imperative Programmiersprache (3GL). Sie ist aber vergleichsweise leicht zu erlernen, die Herausforderung ist meist eher die heterogene Umgebung, in der der Code eingebunden ist und die Verknüpfung: Fachlichkeit zu Code. Dieser kleine Artikel dreht sich um einen Auszug im Alltag eines Mainframe-Entwicklers. Oft totgesagt, setzen immer noch viele Firmen (Banken, Versicherungen) einen Mainframe ein, da er sicher, zuverlässig und schnell auch große Datenmengen verarbeitet: Ein Consist-Kunde, eine Versicherungsgesellschaft, nutzt den Mainframe und viele Anwendungen sind in COBOL geschrieben. Dabei sind die Oberflächen teils noch in CICS-Masken verfasst, meist aber schon auf Java-Basis. Gesetzliche und fachliche Anforderungen sorgen für eine konstante Weiterentwicklung, dabei sind die eingesetzten Tools durchaus modern.

Entwickelt werden kann mit einem erweiterten UltraEdit:UltraEdHier sieht man einen Code-Ausschnitt zu einer Section, die am Anfang des Programms ausgeführt wird. Es geht u. a. um Initialisierungen von Variablen und Vorbelegungen von Basisfeldern.

Oder mit dem Enterprise Developer (Eclipse):EnterpriseDev

Die Sourcen werden mit Serena Dimensions und mit Git verwaltet. Da es immer mehr Schnittstellen zu moderneren Systemen geben muss, wird auch Code generiert, beispielsweise über COBOL-Kapseln mittels des Tools Innovator. Unser Tag als SystemanalytikerIn bei Consist beginnt meist mit dem Check der Job-Ausgaben im TSO-Tool Beta92: Jede Nacht laufen diverse Verarbeitungen (Batchjobs, verfasst in der JobControlLanguage), damit z. B. Versicherungsscheine oder Rechnungen erzeugt werden können. Tritt ein Fehler auf, soll natürlich nicht der komplette Job abbrechen, sondern es wird nur der fehlerhafte Vertrag ausgegeben, verbunden mit einer (hoffentlich) aussagekräftigen Fehlermeldung. Nun schauen wir in unserer Dokumentation nach, ob der Fehler bekannt ist, oder versuchen ihn nachzustellen. Es kann auch einen so genannten Dump geben: Ein Abbild des Systems zum Abbruchzeitpunkt, das man analysieren kann.

tso1tso2tso3tso4

Der Überläufer

So fiel uns eines Tages eine Meldung auf, welche uns bisher komplett unbekannt war – wir machten uns also gemeinsam auf die Fehlersuche: Zuerst schauten wir uns die Protokolle zu dem abgebrochenen Job und die aufgerufenen Programme genauer an. Dabei ist uns aufgefallen, dass wir an den Programmen schon seit längerer Zeit keine Veränderungen mehr vorgenommen hatten, die Abbruchursache aber eine Endlosschleife war. Woher diese nun plötzlich kam, war uns zunächst schleierhaft, bis einem Kollegen einfiel, dass vor einer Weile der Compiler von COBOL4 auf COBOL5 umgestellt wurde – so kamen wir dem Problem auf die Schliche:

Es lag in der Behandlung von COMP-Feldern (dabei handelt es sich um eine Datenspeicherung in gepackter Form: Einerseits geht es dabei um eine Einsparung von Speicherkapazität, aber auch um eine bessere Performance bei Rechenoperationen mit diesen Feldern). Ein auf vier Stellen definiertes COMP-Feld (PIC 9(4) COMP) geht laut Definition nur bis 9999, technisch handelt es sich dabei aber um einen Small-Int, welcher bis 32767 ginge; danach würde ein Überlauf erfolgen. Im betroffenen Programm wurde diese COMP-Variable als Zähler verwendet und der Wert überstieg regelmäßig den eigentlich vorgesehenen Wert von 9999. Die Variable war also nun zu klein definiert. Aufgrund der Technik im Hintergrund trat jedoch kein Fehler auf und das Programm arbeitete weiter wie gewünscht. Mit dem nun neu eingeführten Compiler funktionierte das Hochzählen anders und die zu hohen Zahlen wurden abgeschnitten. Mit dem vorigen Compiler war also 9999 + 1 = 10000, mit dem neuen jedoch nur 0, weil die vorne stehende 1 abgeschnitten wurde und 4 x 0 = 0.

Neben den Jobkontrollen und kleineren Anfragen der Kund:innen kümmern wir uns um Anforderungen oder Fehlerkorrekturen (die erreichen uns über HP Alm oder den HP Service Manager).

Projekt/Anforderung: DUVE

Z. B. hat der Fachbereich den Wunsch, dass Neuordnungen (d. h. die Umstellung des Vertrags auf ein aktualisiertes Versicherungsprodukt; Abk. NO) von Junge-Erwachsenen-Sachversicherungsverträgen auf den Standard-Tarif nicht mehr manuell von den Anwendern durchgeführt werden sollen, sondern automatisiert. Das spart viel Zeit und ist weniger fehleranfällig. Abhängig vom 30. Geburtstag des Versicherungsnehmers und der Vertragsfälligkeit (die basiert auf dem Versicherungsablauf) sollen alle Schritte, die sonst in der Java-Oberfläche (dort laufen die COBOL-Programme auf einem Server, nicht auf dem HOST) vorgenommen werden, nachts in einem Job als Dunkelverarbeitung (Duve) ablaufen: inklusive der Erzeugung des Scheins, der Provisionsschnittstellen, usw. Das klingt zunächst simpel, aber es sind leider dutzende Programme beteiligt, die natürlich ganz anders eingebunden sind. In der Anforderung wird nun nicht im Detail spezifiziert, was genau mit den Vertragsdaten in den DB2-Tabellen passieren soll. Es wird vorgegeben, dass im Ergebnis die gleichen Einträge erzeugt werden sollen, wie bei dem manuellen Vorgang:

Man kann nun entweder die Tabelleninhalte vor und nach der NO vergleichen und komplett neuen Code verfassen, der aber ggf. nicht alle Ausnahmen und Feinheiten der historisch gewachsenen Serverprogramme abbildet.

Oder man geht komplett durch alle Serverprogramme und nimmt nur die Programmsektionen, die für die NO nötig sind.

Wir haben uns für Letzteres entschieden, dafür eine Übersichtsdatei erzeugt, welche Sektionen relevant sind, was grob darin durchgeführt wird und in welcher Reihenfolge. Die Beitragsberechnung mussten wir in ein separates COBOL-Modul auslagern, da der Prozess an sich schon sehr komplex ist und wir den Part gut an eine separate Entwicklerin weitergeben konnten.

Anbei der grobe Ablauf:

  • In einem Batchmodul A erfolgt die Markierung der Verträge, die für eine Duve in Frage kommen (wenn keine Mahnung im Zentralinkasso aktiv ist und keine schwebende Bearbeitung): In einer DB2 Tabelle wird ein Markierungseintrag erzeugt
  • Batchmodul B liest monatlich diese Markierungen und prüft auch noch mal diverse Plausibilitäten. Dann erfolgt das Ermitteln des neuen Standard-Produktes passend zur Produktgeneration des Jungen-Erwachsenen-Vertrags mit den entsprechenden Vertragsbausteinen (z. B. ein Hausrat-Baustein und einer für versicherte Elementarschäden). Auszug aus den Programmsektionen:
    • Prüfung der Elementarzone
    • Prüfung: Ist der Vertrag noch ein „Junge Erwachsene (JE)-Vertrag“
    • Lesen des aktuellen JE-Vertrags in den verschiedenen DB2-Tabellen 
    • Es wird in einer Schleife über alle Vertragsteile gelesen: JE-Nachfolger ermitteln
    • Lesen der Objektarteigenschaften des alten und des neuen Produktbausteins (z. B. die Wohnfläche in m2 bei Hausrat, denn der Wert muss u. a. übernommen werden)
    • Texte, Rabatte oder Zuschläge, Selbstbeteiligungen und Leistungsvarianten wenn möglich übernehmen
    • Schreiben der Daten, auch in anderen angeschlossenen Systemen, die auch Vertragsdaten vorhalten
    • Schreiben der Batchaufträge für die Tagesverarbeitung am Folgetag, damit Zentralinkasso, etc. die Schnittstellendaten erhalten
    • Historisierung des Vertragsstandes vor der Neuordnung
    • Commit- und Rollback-Logik

Die Expertenschätzung belief sich dann auf über 80 Entwicklungstage: Das übersteigt die Anzahl möglicher Entwicklerstunden für das Zielrelease (Zeitpunkt der Produktivsetzung), insbesondere, weil andere Anforderungen auch parallel umgesetzt werden müssen. Zudem darf das Tagesgeschäft nicht leiden (Jobkontrolle / Auswertungen / kleine Anfragen bearbeiten / Fehler korrigieren / Reports für die Kund:innen)! Die Priorität wurde aber so hoch angesetzt, dass wir bei unseren Kollegen um Unterstützung gebeten haben: Zum Glück betreuen wir mehrere Systeme dieser Art und können im Notfall meist ein Teammitglied „ausleihen“.  Wie üblich bei solch großen Projekten ergab sich während der Umsetzung noch einiges an Extrawünschen und es sind Probleme aufgefallen, die so nicht vorhersehbar waren.

Beispiele:

  • Probleme bei dem Ermitteln des Mahnstatus wegen IMS statt DB2
  • Die Beitragsberechnung musste noch an einigen Stellen manuell angepasst/erweitert werden
  • Wenn Versicherungs-Beginn und -Ablauf identisch sind, soll der Ablauf um 1 Jahr erhöht werden
  • Es sollen nur die Versicherungsnehmer:innen ein spezielles Ankündigungsschreiben erhalten, die keinen Mahnstatus, keine schwebende Bearbeitung und ein eingetragenes Geburtsdatum haben

Der Job, der das Programm aufruft, ist nicht kompliziert. Die entscheidenden Stellen:

//Z12GGTT1 JOB 00009999,ETT66437,MSGCLASS=T,CLASS=H,SCHENV=RAA1,                
//             MSGLEVEL=(1,1),                                               
//             NOTIFY=&SYSUID    …//STEP2   EXEC DBENTT,MBR=TTB6002Z,PSB=TTB6002Z,PLAN=RAPB00AE,              
//             DBRC=N                                                  
//G.SYSUDUMP DD SYSOUT=*   …//EOVORL   DD  *                                                          
V SA DENAM--- = WERT         /*  KOMMENTAR                                
+ AA MDANT    = +0000000066  /*  AA
+ AA AKTMO    = 06.2020      /*  AKTUELLER MONAT/-JAHR                    
+ AA SCHAR    = SCHARF       /*  UNSCHARF / SCHARF COMMIT                                                                                  

In der ersten Zeile steht der TSO-Login, eine Job-ID, und z. B. auch eine Angabe zur Umgebung (SCHENV), da die verschiedenen Entwicklungs- und Testumgebungen sauber getrennt sind.

Hinter MBR (Member) steht der Name des Batch-Moduls, was aufgerufen wird. Parameter werden dem Programm in der Vorlaufkarte (EOVORL) mitgegeben, z. B. das Fälligkeitsdatum (Monat.Jahr), oder ob der Job scharf (mit Aktualisierungen der Tabellen) oder unscharf (kein Insert / kein Update) laufen soll. Die Angabe des Plans ist für den DB2-Zugriff relevant und der PSB für den Zugriff auf IMS.

Nach dem Submitten des Jobs kann man sich die Ergebnisse anschauen. Diese Ausgaben kann man selbst im Cobol-Programm definieren und so z. B. eine Statistik erzeugen, wie viele Verträge dunkelverarbeitet wurden, ob es Fehler gab, ob bereits Verträge manuell neu geordnet worden sind, usw. Bricht der Job ab, werden dort auch Angaben zum Abbruch geloggt. Tiefer kann man dann aber mit dem Fault Analyzer einsteigen. Das Cobol-Programm hatte am Ende, Cobol-Kenner:innen werden es ahnen, viele Zeilen Code: ca. 13.000.

Fazit

Schlussendlich ist das Entwickeln auf dem HOST interessant und es gibt durchaus viel Abwechslung. Man vermisst vielleicht ab und an die Funktionalitäten moderner Frameworks anderer Sprachen und muss einiges „per Hand“ programmieren, dafür ist der Code gut nachvollziehbar und im debug landet man nicht ständig in unterschiedlichen Fassadenklassen, o. ä. Wenn man also ab und an mit den Anspielungen auf Dinosaurier oder Lochkarten leben kann, ist man in der Mainframe-Welt gut aufgehoben. Es gibt ja zum Glück auch genug Vorurteile über die "modernen" Sprachen...