This is a test message to test the length of the message box.
Login
ABAP Tipp CLEAR right
Erstellt von Software-Heroes

ABAP Tipp - CLEAR right

115

Richtig löschen? In diesem Artikel wollen wir uns einmal anschauen, wann es Sinn macht zu löschen und wie du effektiv vorgehen kannst.

Werbung

Wie solltest du heutzutage in der Entwicklung deine Variablen löschen, musst du das überhaupt noch machen und welche Hilfen können wir dir mit auf den Weg gehen. In diesem Artikel wirst du etwas mehr erfahren und zum Löschprofi von uns ausgebildet. Also lehn dich zurück und genieße den Artikel.

 

Einleitung

Manchmal machen dir Kleinigkeiten bereits das Leben leichter oder eben schwerer, wenn du auf der Suche nach Fehlern bist. Neben dem Löschen von Variablen gibt es auch andere Methoden, um die Daten zu initialisieren und dabei in weniger Probleme zu laufen. Selbst mit dem Design deiner Software kannst du bereits vorher viele Probleme aus dem Weg räumen und die Stabilität erhöhen.

Neben dem direkten Löschen von Variableninhalten, gibt es auch das Überschreiben, den Garbage Collector und das Design deiner Software, die in Betracht gezogen werden können.

 

CLEAR

Die einfachste Methode zum Aufräumen deiner Variablen ist das einfache Löschen von Variablen, hierbei stehen dir CLEAR, REFRESH und FREE zur Verfügung. Wir empfehlen aber nur noch die Verwendung eines Statements. REFRESH ist obsolet und FREE arbeitet so ähnlich wie CLEAR, weshalb auch vom Namen her CLEAR am besten passt. Dazu einmal ein Beispiel verschiedener Weisen:

" Clear variable (single)
CLEAR ld_field.

" Clear variable (chained statement)
CLEAR: ls_structure, lo_reference.

" Clear table
CLEAR: lt_table.

" Clear table (with header line)
CLEAR: lt_table, lt_table[].

 

Angefangen vom einfachen Löschen von Variablen, Strukturen und Referenzen, bis hin zum Löschen von Tabellen und Tabellen mit Kopfzeilen.

Hinweis: Die Variante zum Löschen von Tabellen mit Kopfzeilen "[]" kann bei anderen Entwicklern zu Verwirrungen führen, wenn es sich nur um eine einfache Tabelle handelt. Wir empfehlen daher hier mit Bedacht die korrekte Variante zu wählen, auch da Quellcode eingespart werden kann.

 

Globale Variablen

Variablen die global definiert sind, egal ob in einer Klasse oder einem Report, können zu Fehlern führen, wenn sie bei der Nutzung nicht den richtigen Wert haben oder nicht sauber gelöscht wurden. In der Vergangenheit wurden oft Tabellen und Strukturen, über die geloopt wird, global definiert und sehr wahrscheinlich in Unterroutinen verwendet. Solche Verarbeitungen bergen ein sehr großes Risiko, da man nie weiß, ob die Variablen zum Zeitpunkt der Verarbeitung immer noch korrekt gefüllt sind.

 

Lokale Variable

Bereits der Umstieg auf lokale Variablen reduziert dieses Problem und sorgt in maximal einer Methode für Probleme. Die Variablen werden nach dem Verlassen der Methode vom Garbage Collector des Systems gelöscht und werden beim nächsten Aufruf der Methode wieder initial gesetzt.

DATA:
  lt_table     TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
  ls_structure TYPE ts_return.

" Loop with predefined variable
LOOP AT lt_table INTO ls_structure.
ENDLOOP.

 

Inline Deklaration

Die Inline Deklaration erzeugt die Variable da wo wir sie brauchen und zeigt an, dass diese Variable zum Beispiel nur für den Loop benötigt wird.

" Loop with inline deklaration
LOOP AT lt_table INTO DATA(ls_inline).
ENDLOOP.

 

Exporting Parameter

Eine weitere Gefahrenquelle sind Exporting Parameter. Wird der Wert der Exporting Variablen nicht sauber gelöscht, dann kann es je nach Konstellation zu Fehlern kommen. Definieren wir dazu die folgende Methode:

" Definition
METHODS:
  method_with_exporting
    IMPORTING
      id_param1  TYPE i
      id_param2  TYPE i
    EXPORTING
      ed_result1 TYPE td_char
      ed_result2 TYPE i
      ed_subrc   TYPE i.
      
" Implementation
METHOD method_with_exporting.
  ed_result1 &&= 'Test'.
  ed_result2 += id_param1 + id_param2.
  ed_subrc = 2.
ENDMETHOD.

 

Führen wir dazu eine Verarbeitung in drei Schritten aus und stellen die Methode in eine DO Schleife, die drei Mal ausgeführt wird. Bei dieser Kombination verwenden wir eine Inline Deklaration und definieren die Variable für den Aufruf der Methode.

DO 3 TIMES.
  method_with_exporting(
    EXPORTING
      id_param1  = 1
      id_param2  = 2
    IMPORTING
      ed_result1 = DATA(ld_result1)
      ed_result2 = DATA(ld_result2)
      ed_subrc   = DATA(ld_subrc)
  ).
ENDDO.

 

Prüfen wir nun das Ergebnis der Variablen, würden wir eigentlich ein anderes Ergebnis erwarten. Die Exporting Variablen werden nach dem zweiten Aufruf der Methode nicht initialisiert und der alte Wert führt zu einem fehlerhaften Ergebnis.

 

Hier solltest du nach dem Aufruf der Methode sofort auch die Exporting Parameter bereinigen, hier könnten noch alte Werte aus einer vorhergehenden Verarbeitung enthalten sein. Das Problem kann vor allem bei Tabellen auftreten, wenn immer wieder Zeilen ans Ende angehangen werden. Ein einfacher CLEAR kann hier schwerwiegende Probleme beheben.

METHOD method_with_exporting.
  CLEAR: ed_result1, ed_result2, ed_subrc.

  ed_result1 &&= 'Test'.
  ed_result2 += id_param1 + id_param2.
  ed_subrc = 2.
ENDMETHOD.

 

Methoden Design

Um das Problem mit den Exporting Parametern zu umgehen, lohnt sich bereits beim Design der Methode auf Exporting Parameter zu verzichten. Laut Clean ABAP, sollte die Methode nur wenige Importing Parameter und einen Returning Parameter besitzen, damit gilt die Methode als Clean. Dieser Umstand sorgt auch dafür, dass wir nicht mehr an den CLEAR bei den Rückgabeparametern denken müssen.

DO 3 TIMES.
  DATA(ls_result) = method_with_returning( id_param1 = 1 id_param2 = 2 ).
ENDDO.

 

Rufen wir nun die Returning Methode drei Mal in Folge auf und verwenden ebenfalls die Inline Deklaration, dann sehen wir mit der gleichen Logik nach jedem Durchlauf das richtige Ergebnis. Wir müssen nun nicht mehr die Variablen vorher löschen und sparen damit weiteren Code, ebenfalls sieht der Aufruf viel schlanker aus.

 

Konstruktor Ausdrücke

Wie der Name bereits beschreibt, legen solche Ausdrücke immer wieder neue Variablen an und löschen damit den alten Wert automatisch aus der Variable.

 

Befüllung

Schauen wir uns einmal das folgende Beispiel an:

ls_structure-result1 = 'One'.
ls_structure-result2 = 10.
ls_structure-subrc = 1.
INSERT ls_structure INTO TABLE lt_table.

ls_structure-result1 = 'Two'.
ls_structure-subrc = 2.
INSERT ls_structure INTO TABLE lt_table.

 

Der zweite Eintrag wird sehr wahrscheinlich einen Fehler haben und das Feld RESULT2 wird den Inhalt des vorherigen Eintrags besitzen. Hier ist ebenfalls nicht klar, ob das Verhalten so gewünscht ist oder es sich um einen Fehler handelt. Mit dem Löschen der Variablen können wir den Fehler vermeiden:

CLEAR ls_structure.
ls_structure-result1 = 'One'.
ls_structure-result2 = 10.
ls_structure-subrc = 1.
INSERT ls_structure INTO TABLE lt_table.

CLEAR ls_structure.
ls_structure-result1 = 'Two'.
ls_structure-subrc = 2.
INSERT ls_structure INTO TABLE lt_table.

 

Allerdings schreiben wir immer noch recht viel Code und das könnten wir weiter reduzieren, ohne auf den CLEAR achten zu müssen. Dazu verwenden wir direkt einen Konstruktor Ausdruck und sparen uns die Variable, aber auch einiges zum Tippen:

INSERT VALUE #(
  result1 = 'One'
  result2 = 10
  subrc = 1
) INTO TABLE lt_table.

INSERT VALUE #(
  result1 = 'Two'
  subrc = 2
) INTO TABLE lt_table.    

 

Schleife

In Schleifen arbeiten wir meist mit Mappings und Datenzuweisungen, um die Daten zu verarbeiten. Bevor du mit der Arbeitsstruktur arbeitest, solltest du sie durch einen CLEAR erst einmal initialisieren. Dies kann man am Ende der Schleife machen oder am Anfang. Wir empfehlen das Löschen am Anfang der Schleife, von der Leserichtung beim Suchen nach Fehlern, würde man zuerst prüfen, ob die Struktur sauber initialisiert wurde.

LOOP AT lt_table INTO ls_line.
  CLEAR ls_structure.
  ls_structure-result1 = ls_line-result1.
  ls_structure-result2 = 2.
ENDLOOP.

 

Auch hier kannst du das CLEAR sparen, wenn du per Konstuktor Ausdruck die Variable erzeugst oder befüllst:

LOOP AT lt_table INTO ls_line.
  ls_structure = VALUE #(
    result1 = ls_line-result1
    result2 = 2
  ).
ENDLOOP.

 

Vollständiges Beispiel

Zum Abschluss noch das komplette Beispiel zum selbst Ausprobieren oder Nachstellen im eigenen System:

CLASS zcl_bs_demo_clear_right DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
    TYPES:
      td_char TYPE c LENGTH 20,

      BEGIN OF ts_return,
        result1 TYPE td_char,
        result2 TYPE i,
        subrc   TYPE i,
      END OF ts_return.

    METHODS:
      method_with_exporting
        IMPORTING
          id_param1  TYPE i
          id_param2  TYPE i
        EXPORTING
          ed_result1 TYPE td_char
          ed_result2 TYPE i
          ed_subrc   TYPE i,

      method_with_returning
        IMPORTING
                  id_param1        TYPE i
                  id_param2        TYPE i
        RETURNING VALUE(rs_result) TYPE ts_return,

      simple_clear,

      global_variable,

      constructor_expressions.
ENDCLASS.


CLASS zcl_bs_demo_clear_right IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    simple_clear( ).
    global_variable( ).

    DO 3 TIMES.
      method_with_exporting(
        EXPORTING
          id_param1  = 1
          id_param2  = 2
        IMPORTING
          ed_result1 = DATA(ld_result1)
          ed_result2 = DATA(ld_result2)
          ed_subrc   = DATA(ld_subrc)
      ).
    ENDDO.

    DO 3 TIMES.
      DATA(ls_result) = method_with_returning( id_param1 = 1 id_param2 = 2 ).
    ENDDO.

    constructor_expressions( ).
  ENDMETHOD.


  METHOD simple_clear.
    DATA:
      ld_field     TYPE i,
      ls_structure TYPE ts_return,
      lt_table     TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
      lo_reference TYPE REF TO zcl_bs_demo_clear_right.

    " Clear variable (single)
    CLEAR ld_field.

    " Clear variable (chained statement)
    CLEAR: ls_structure, lo_reference.

    " Clear table
    CLEAR: lt_table.

    " Clear table (with header line)
    CLEAR: lt_table, lt_table[].
  ENDMETHOD.


  METHOD global_variable.
    DATA:
      lt_table     TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
      ls_structure TYPE ts_return.

    " Loop with predefined variable
    LOOP AT lt_table INTO ls_structure.
    ENDLOOP.

    " Loop with inline deklaration
    LOOP AT lt_table INTO DATA(ls_inline).
    ENDLOOP.
  ENDMETHOD.


  METHOD method_with_exporting.
    CLEAR: ed_result1, ed_result2, ed_subrc.

    ed_result1 &&= 'Test'.
    ed_result2 += id_param1 + id_param2.
    ed_subrc = 2.
  ENDMETHOD.


  METHOD method_with_returning.
    rs_result-result1 &&= 'Test'.
    rs_result-result2 += id_param1 + id_param2.
    rs_result-subrc = 2.
  ENDMETHOD.


  METHOD constructor_expressions.
    DATA:
      lt_table     TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
      ls_line      TYPE ts_return,
      ls_structure TYPE ts_return.

    CLEAR ls_structure.
    ls_structure-result1 = 'One'.
    ls_structure-result2 = 10.
    ls_structure-subrc = 1.
    INSERT ls_structure INTO TABLE lt_table.

    CLEAR ls_structure.
    ls_structure-result1 = 'Two'.
    ls_structure-subrc = 2.
    INSERT ls_structure INTO TABLE lt_table.

    INSERT VALUE #(
      result1 = 'One'
      result2 = 10
      subrc = 1
    ) INTO TABLE lt_table.

    INSERT VALUE #(
      result1 = 'Two'
      subrc = 2
    ) INTO TABLE lt_table.


    LOOP AT lt_table INTO ls_line.
      CLEAR ls_structure.
      ls_structure-result1 = ls_line-result1.
      ls_structure-result2 = 2.
    ENDLOOP.

    LOOP AT lt_table INTO ls_line.
      ls_structure = VALUE #(
        result1 = ls_line-result1
        result2 = 2
      ).
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Wie du siehst, ist das Löschen nicht unbedingt schwer, es kommt nur auf die richtige Sichtweise an und wie du für dich mit dem Thema Software-Architektur bzw. Software-Design umgehst. Wir hoffen die Tipps haben dir geholfen, noch einmal das Thema zu durchdringen und du nimmst etwas für deine tägliche Arbeit mit.


Enthaltene Themen:
TippCLEARRichtig löschen
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


ABAP Tipp - Performance Kettensätze

Kategorie - ABAP

Schauen wir uns hier einmal die Performance beim Bilden von Kettensätzen mit DATA und FIELD-SYMBOL an. Welche Variante wird bei der Performance vorn liegen?

28.04.2023

ABAP Tipp - Adobe Formulare zu groß

Kategorie - ABAP

In diesem kleinen Tipp wollen wir uns anschauen, wieso im schlechtesten Fall Adobe Formulare größer werden, als sie eigentlich sein sollten.

18.11.2022

ABAP - ALV in 2022 noch relevant?

Kategorie - ABAP

Heute mal die scherzhafte Frage, benötigen wir im Jahr 2022 noch Reports die ALV Ausgaben erzeugen? Der Frage wollen wir in diesem Artikel einmal nachgehen.

01.07.2022

ABAP im Wandel

Kategorie - ABAP

Die Programmiersprache ABAP ist bereits seit Jahren im Wandel und modernisiert sich in verschiedenen Konzepten. In diesem Artikel schauen wir uns das einmal im Detail an.

24.06.2022

ABAP Tipp - Clean Core

Kategorie - ABAP

In diesem Artikel mal etwas zum Thema Clean Core, was bedeutet es für den Entwickler, was sind Vorraussetzungen und auf was muss man achten.

17.06.2022