Verzweigte ABAP-Programmlandschaft mit einer kontrolliert hervorgehobenen und geprüften Codeänderung

Gewachsenen ABAP-Code sicher ändern: Mein Vorgehen in sieben Schritten

Die eigentliche Änderung umfasst manchmal nur zehn Zeilen ABAP. Der schwierige Teil ist herauszufinden, an welcher Stelle diese zehn Zeilen hingehören und welche bestehenden Abläufe sie beeinflussen.

Das gilt besonders für gewachsene SAP-Anwendungen: Reports mit vielen Includes, Funktionsgruppen, User Exits, BAdIs, Dynpros, ALV-Ereignisse, Hintergrundjobs und Aufrufe weiterer Transaktionen. Der Code bildet oft Jahre an Prozesswissen ab. Ein Teil davon ist dokumentiert, ein Teil steckt nur noch in Prüfungen, Statusabfragen und Sonderfällen.

In solchen Situationen beginne ich nicht mit dem Umbau. Ich rekonstruiere zuerst den fachlichen und technischen Ablauf. Erst wenn klar ist, woher Daten kommen, wo Entscheidungen fallen und welche Folgeprozesse ausgelöst werden, lässt sich eine Änderung belastbar entwerfen.

Meine wichtigste Regel lautet deshalb: Unbekannten ABAP-Code nicht zuerst verschönern, sondern zuerst verstehen und absichern.

Warum kleine Änderungen im Bestand riskant sein können

Die Anzahl geänderter Codezeilen sagt wenig über das Risiko aus. Eine zusätzliche Bedingung kann beispielsweise beeinflussen,

  • welche Belege selektiert werden,
  • ob eine Sperre gesetzt oder wieder aufgehoben wird,
  • welche Berechtigungsprüfung greift,
  • ob eine Verarbeitung im Dialog oder im Hintergrund läuft,
  • ob Folgeprogramme per Funktionsbaustein, SUBMIT oder Transaktionsaufruf gestartet werden,
  • wie Status, Protokoll und Fehlermeldungen fortgeschrieben werden.

Gerade in Logistikprozessen hängen an einer scheinbar lokalen Entscheidung häufig weitere Schritte. Lieferung, Kommissionierung, Transportauftrag, Warenausgang und Fakturierung sind technisch getrennt, fachlich aber miteinander verbunden.

Das Problem ist daher selten nur „alter Code“. Das Problem ist fehlende Transparenz über Verantwortlichkeiten und Auswirkungen.

1. Die fachliche Änderung in einem Satz klären

Bevor ich Quelltext analysiere, formuliere ich das gewünschte Ergebnis möglichst konkret. Nicht: „Die Selektion muss angepasst werden.“ Besser:

Lieferungen mit Merkmal X sollen bei der automatischen Wellenbildung der Regel Y zugeordnet werden; die manuelle Bearbeitung bleibt unverändert.

Dieser Satz grenzt bereits mehrere Dinge ab:

  • betroffenes Geschäftsobjekt,
  • auslösendes Merkmal,
  • gewünschte Entscheidung,
  • betroffener Verarbeitungspfad,
  • ausdrücklich nicht betroffener Ablauf.

Danach kläre ich die Abnahmekriterien. Welche Fälle müssen funktionieren? Welche dürfen sich nicht verändern? Welche Fehlerreaktion wird erwartet? Ohne diese Punkte ist später kaum feststellbar, ob die Änderung fachlich korrekt oder nur technisch lauffähig ist.

2. Einstiegspunkte und Varianten bestimmen

Ein Programmname allein beschreibt den Prozess selten vollständig. Derselbe Code kann über eine Transaktion, einen Job, ein anderes Programm, einen RFC-Aufruf oder eine Fiori-Anwendung erreicht werden. Außerdem verändern Selektionsvarianten, Customizing und Benutzerberechtigungen das Verhalten.

Ich erfasse deshalb zuerst:

  • Transaktion, Report, Service oder Job als Einstiegspunkt,
  • relevante Selektions- und Layoutvarianten,
  • aufrufende Programme oder Schnittstellen,
  • Dialog- und Hintergrundverarbeitung,
  • Benutzerrollen und organisatorische Ebenen,
  • beteiligte Customizing-Einstellungen.

Dabei hilft ein realistischer Testfall mehr als eine abstrakte Beschreibung. Mit einem konkreten Beleg lassen sich Datenfluss, Verzweigungen und Folgeaktionen gezielt verfolgen.

3. Den Aufruf- und Datenfluss kartieren

Jetzt entsteht eine technische Landkarte. Bei einem klassischen ABAP-Programm beginne ich typischerweise mit Ereignisblöcken, Includes, zentralen FORM-Routinen, Methoden und Funktionsbausteinen. Danach folge ich den Stellen, an denen Daten gelesen, verändert, geprüft oder gespeichert werden.

Besonders wichtig sind für mich:

  • Datenbankzugriffe und aufgerufene APIs,
  • zentrale interne Tabellen und Strukturen,
  • Status- und Berechtigungsprüfungen,
  • Enqueue- und Dequeue-Aufrufe,
  • Erweiterungspunkte wie BAdIs und Exits,
  • CALL FUNCTION, SUBMIT, RFC- und Transaktionsaufrufe,
  • Update-Task, Commit-Grenzen und Fehlerbehandlung,
  • Application Log, Nachrichten und Rückgabewerte.

Die vollständige Dokumentation jedes Unterprogramms wäre meist unwirtschaftlich. Entscheidend ist die Kette vom fachlichen Eingang bis zur sichtbaren Wirkung.

Eine kompakte Darstellung reicht oft aus:

Einstieg → Selektion → Anreicherung → fachliche Prüfung → Entscheidung → Speichern → Folgeprozess → Protokoll

An dieser Kette lässt sich später zeigen, wo die neue Logik eingreift und welche Abschnitte unverändert bleiben.

4. Annahmen mit dem Debugger prüfen

Statische Codeanalyse zeigt mögliche Pfade. Sie zeigt nicht automatisch, welcher Pfad für den konkreten Fall tatsächlich ausgeführt wird.

Im Debugger arbeite ich deshalb mit Hypothesen. Zum Beispiel:

  • Die Zuordnung wird in Routine A entschieden.
  • Der benötigte Wert ist zu diesem Zeitpunkt bereits vorhanden.
  • Bei automatischer Verarbeitung wird derselbe Pfad wie im Dialog genutzt.
  • Ein Customer Exit verändert die Daten vor dem Speichern.

Gezielte Breakpoints, Watchpoints und die Prüfung weniger zentraler Datenobjekte liefern schneller Klarheit als das lineare Durchsteppen durch tausende Anweisungen. Ebenso wichtig ist die Negativprobe: Welche erwartete Routine wird gerade nicht durchlaufen und warum?

Das Ergebnis dieses Schritts ist kein Bauchgefühl, sondern ein bestätigter Ist-Ablauf für repräsentative Fälle.

5. Den kleinsten fachlich sauberen Eingriff wählen

„Möglichst wenig Code ändern“ ist als Ziel zu ungenau. Eine Ein-Zeilen-Anpassung an der falschen Stelle kann riskanter sein als eine klar abgegrenzte Methode mit Tests.

Ich suche deshalb nach dem kleinsten fachlich sauberen Eingriff:

  • Gibt es einen vorgesehenen BAdI oder Enhancement Point?
  • Kann die neue Regel hinter einer klaren Schnittstelle gekapselt werden?
  • Liegen alle benötigten Daten am gewählten Punkt zuverlässig vor?
  • Wird die Logik genau einmal ausgeführt?
  • Bleiben Sperren, Updates und Commit-Verhalten unverändert?
  • Funktioniert die Lösung auch für Massenverarbeitung und Hintergrundjobs?

Wenn neue Fachlogik in einen prozeduralen Bestand integriert werden muss, ist eine gekapselte Klasse oft sinnvoll. Der bestehende Ablauf bleibt erkennbar, während die Entscheidung separat implementiert und getestet werden kann.

Ein vollständiges Refactoring des Altprogramms ist dafür meist nicht erforderlich. Es erhöht den Änderungsumfang und erschwert die fachliche Abnahme. Größere strukturelle Verbesserungen sollten einen eigenen Auftrag und eigene Tests erhalten.

6. Wirkung und Nebenwirkungen messen

Code Review und Debugging beantworten nicht jede Frage. Sobald Laufzeit, Datenmenge oder Datenbankzugriffe relevant sind, sollte gemessen werden.

Je nach System und Fragestellung kommen unter anderem diese Werkzeuge infrage:

  • ATC für Qualitätsprüfungen, Performance-Hinweise, Standards und weitere technische Findings,
  • ABAP Unit für wiederholbare Tests gekapselter Fachlogik,
  • SAT beziehungsweise ABAP Profiler für Laufzeit und Aufrufhierarchie,
  • ST05 für die detaillierte Analyse von SQL-Zugriffen,
  • SQL Monitor für SQL-Verhalten unter realer Systemnutzung,
  • Application Log für nachvollziehbare Verarbeitung im Betrieb.

Dabei gilt: Ein ATC-Finding ist ein Hinweis, keine vollständige fachliche Bewertung. Umgekehrt ist ein grüner ATC-Lauf kein Beweis dafür, dass Prozess und Ergebnis korrekt sind.

Bei Performancefragen verlasse ich mich nicht auf Vermutungen wie „die Schleife sieht teuer aus“. Relevant sind reale Datenmengen, Anzahl der Aufrufe, Laufzeit und Datenbanklast. Erst die Messung zeigt, ob der vermutete Engpass tatsächlich der Engpass ist.

7. Fachliche Regression und Betrieb mitdenken

Ein positiver Testfall reicht bei Bestandscode selten aus. Ich plane mindestens drei Gruppen:

  1. Der neue Fall verhält sich wie gefordert.
  2. Bestehende Fälle verhalten sich unverändert.
  3. Fehler- und Grenzfälle bleiben beherrscht.

Dazu gehören je nach Anwendung fehlende Stammdaten, gesperrte Belege, unvollständiges Customizing, Mehrfachselektion, parallele Verarbeitung, Berechtigungsfehler und ein abgebrochener Folgeprozess.

Für produktionsnahe Änderungen prüfe ich außerdem:

  • Ist im Fehlerfall erkennbar, was verarbeitet wurde?
  • Kann ein Job oder Beleg kontrolliert erneut verarbeitet werden?
  • Entstehen doppelte Buchungen oder Aktionen bei Wiederholung?
  • Gibt es ein belastbares Protokoll für Support und Fachbereich?
  • Welche Beobachtung ist direkt nach der Produktivsetzung sinnvoll?

Die Änderung ist nicht mit dem erfolgreichen Transport abgeschlossen. Sie ist abgeschlossen, wenn sie im realen Prozess nachvollziehbar funktioniert und bei Problemen analysierbar bleibt.

Vier Fehler, die ich vermeiden würde

Direkt an der sichtbaren Codestelle ändern

Die Stelle, an der ein Wert angezeigt wird, ist nicht zwingend die Stelle, an der er fachlich bestimmt werden sollte. UI-Aufbereitung, Entscheidung und Persistenz müssen getrennt betrachtet werden.

Den Debugger ohne Hypothese verwenden

Wer nur durch den Code steppt, sammelt viele Details und verliert leicht den Prozess. Eine konkrete Frage pro Debugging-Lauf führt schneller zu belastbaren Ergebnissen.

Refactoring und Fachänderung vermischen

Beides kann sinnvoll sein. Zusammen vergrößert es jedoch den Testumfang und erschwert die Zuordnung von Fehlern. Bei kritischen Bestandsprogrammen trenne ich die Schritte, sofern keine technische Notwendigkeit dagegen spricht.

Nur den erfolgreichen Dialogfall testen

Jobs, Varianten, Berechtigungen, Sperren und Massendaten erzeugen andere Pfade. Eine Änderung, die nur mit einem Entwicklerbenutzer und einem einzelnen Testbeleg funktioniert, ist noch nicht produktionsreif.

Eine kompakte Prüfliste

Vor der Umsetzung:

  • Fachliches Ziel und Nicht-Ziele formuliert
  • Einstiegspunkte und Varianten bekannt
  • repräsentative Testfälle vorhanden
  • Aufruf-, Daten- und Updatefluss verstanden
  • Erweiterungspunkte und Berechtigungen geprüft

Vor dem Transport:

  • neue Logik gekapselt und nachvollziehbar benannt
  • Positiv-, Negativ- und Regressionstests durchgeführt
  • ATC-Ergebnisse bewertet
  • Performance bei relevanten Datenmengen geprüft
  • Protokollierung und Fehlerbehandlung verifiziert
  • technische Dokumentation und Betriebsinformation aktualisiert

Meine pragmatische Empfehlung

Bei gewachsenem ABAP-Code würde ich nicht mit einer Modernisierungsdebatte beginnen. Zuerst muss klar sein, welchen Prozess der Code tatsächlich trägt und welche Risiken die konkrete Änderung hat.

Der zuverlässige Weg ist unspektakulär, aber wirksam: fachliches Ziel eingrenzen, Einstiegspunkte bestimmen, Ablauf kartieren, Annahmen im Debugger bestätigen, den Eingriff sauber kapseln und die Wirkung mit Tests und Messungen absichern.

So bleibt eine kleine Änderung auch tatsächlich klein. Und wenn sich bei der Analyse zeigt, dass eine größere Modernisierung notwendig ist, gibt es dafür anschließend eine belastbare Grundlage statt einer Vermutung.

Ähnliche Beiträge