This is a test message to test the length of the message box.
Login
ABAP OO Methodenschnittstelle
Erstellt von Software-Heroes

ABAP OO - Methodenschnittstellen

Wie sollten Methodenschnittstellen aktuell aussehen und wie erreichst du diesen Zustand? In diesem Artikel werden wir die Frage klären.

Werbung

Wie sollte in der heutigen Zeit eigentlich eine Methodenschnittstelle aussehen und was bringen dir eigentlich kleine Schnittstellen bei deiner täglichen Arbeit? Diese Frage wollen wir uns einmal genauer anschauen und dabei auch die Vergangenheit in SAP etwas genauer beleuchten.

 

Vergangenheit

In der Vergangenheit wurden Schnittstellen recht einfach definiert und für jeden Parameter gab es eine eigene Variable. Bei RFC Funktionsbausteinen macht dies auch Sinn, da komplexe Datentypen von Außen schwer ansprechbar sind. Ebenso existieren im System BAPIs in verschiedenen Ausprägungen und Komplexitäten. Wenn du in der letzten Zeit mal einen in dein Coding implementiert hast, wirst du wissen wovon wir reden, die Schnittstellen sind meist nicht sehr übersichtlich.

 

Herausforderung

In der objektorientierten Programmierung sind solche "Monsterschnittstellen" nicht sehr praktikabel, da sie sich schlecht in ein IF Statement packen lassen und die Methoden nicht besonders klein machen. Stell dir deshalb einfach mal das folgende Szenario vor:

  • Deine Klasse muss erweitert werden und du möchtest einen oder mehrere neue Parameter über die Main Methode in die Klasse einschleusen, um im Inneren damit zu arbeiten.
  • Deine Schnittstelle nutzt einzelne Parameter, damit du die Datenübergabe ordentlich regeln kannst.

 

Die Klasse könnte nun wie folgt aussehen und implementiert zur Demonstration nur eine einfache Logik, bei der wir die Parameter an andere Methoden weitergeben, um sie dort zu verwenden.

CLASS zcl_interface_not_clean DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES:
      tt_r_bukrs TYPE RANGE OF t001-bukrs,
      tt_r_waers TYPE RANGE OF t001-waers,

      tt_t001    TYPE STANDARD TABLE OF t001 WITH EMPTY KEY.

    METHODS:
      main
        IMPORTING
          it_r_bukrs TYPE tt_r_bukrs
          it_r_waers TYPE tt_r_waers
          id_butxt   TYPE t001-butxt
          id_test    TYPE abap_bool.

  PROTECTED SECTION.
  PRIVATE SECTION.
    METHODS:
      select_data
        IMPORTING
          it_r_bukrs TYPE tt_r_bukrs
          it_r_waers TYPE tt_r_waers
        EXPORTING
          et_t001    TYPE tt_t001,

      update_data
        IMPORTING
          it_t001  TYPE tt_t001
          id_butxt TYPE t001-butxt
          id_test  TYPE abap_bool.
ENDCLASS.


CLASS zcl_interface_not_clean IMPLEMENTATION.
  METHOD main.
    select_data(
      EXPORTING
        it_r_bukrs = it_r_bukrs
        it_r_waers = it_r_waers
      IMPORTING
        et_t001    = DATA(lt_t001)
    ).

    update_data(
      EXPORTING
        it_t001  = lt_t001
        id_butxt = id_butxt
        id_test  = id_test
    ).
  ENDMETHOD.


  METHOD select_data.
    SELECT *
      FROM t001
      WHERE bukrs IN @it_r_bukrs
        AND waers IN @it_r_waers
      INTO TABLE @et_t001.
  ENDMETHOD.


  METHOD update_data.
    DATA(lt_t001) = it_t001.

    LOOP AT lt_t001 REFERENCE INTO DATA(lr_t001).
      lr_t001->butxt = id_butxt.
    ENDLOOP.

    IF id_test = abap_false.
      UPDATE t001 FROM TABLE lt_t001.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

 

Wollen wir zum Beispiel eine neue Range zur Abfrage der Daten von der Tabelle T001 implementieren, müssen wir einige Stellen anpassen, was mehr Zeit dauert und aufwändiger ist.

 

Lösung

Dazu gibt es auch im Repository von Clean ABAP einen entsprechenden Eintrag. Es wird ebenso empfohlen einen Importing und einen Returning Parameter zu verwenden, da sich die Methoden so am Einfachsten nutzen lassen. Die Herausforderung liegt nun dabei sein Schnittstellen entsprechend aufzubauen. Hier stehen dir im Grunde zwei bewährte Methoden zur Verfügung:

  • Verwendung einer Struktur mit den entsprechenden Merkmalen auf der Strukturebene
  • Verwendung eines Objekts als Datencontainer

 

Beide Methoden haben auch ihren Charme, wir empfehlen aber das Objekt, da du damit am Flexibelsten bist und weitere Logik, sowie Validierungen direkt an die Daten hängen kannst. Außerdem ist ein Objekt änderbar, was bei einer Struktur nicht möglich ist, die nur als Importing übergeben wird.

Dazu legen wir im nächsten Schritt eine Konfiguration an, der Einfachheit verwenden wir kein Interface, sondern bauen direkt die Klasse auf. Wie wir dir in ABAP Unit erklärt haben, sollte aber zur leichteren Testbarkeit ein Interface verwendet werden:

CLASS zcl_test_config DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES:
      tt_r_bukrs TYPE RANGE OF t001-bukrs,
      tt_r_waers TYPE RANGE OF t001-waers.

    DATA:
      mt_r_bukrs TYPE tt_r_bukrs,
      mt_r_waers TYPE tt_r_waers,
      md_butxt   TYPE t001-butxt,
      md_test    TYPE abap_bool.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.


CLASS zcl_test_config IMPLEMENTATION.
ENDCLASS.

 

An dieser Stelle bauen wir nun unsere Ausgangsklasse einmal um und verwenden das neue Konfigurationsobjekt. Bei der Übergabe wird die Schnittstelle schon einmal viel kleiner und ist nun leicht erweiterbar.

CLASS zcl_interface_clean DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES:
      tt_t001 TYPE STANDARD TABLE OF t001 WITH EMPTY KEY.

    METHODS:
      main
        IMPORTING
          io_config TYPE REF TO zcl_test_config.

  PROTECTED SECTION.
  PRIVATE SECTION.
    METHODS:
      select_data
        IMPORTING
                  io_config      TYPE REF TO zcl_test_config
        RETURNING VALUE(rt_t001) TYPE tt_t001,

      update_data
        IMPORTING
          it_t001   TYPE tt_t001
          io_config TYPE REF TO zcl_test_config.
ENDCLASS.


CLASS zcl_interface_clean IMPLEMENTATION.
  METHOD main.
    DATA(lt_t001) = select_data( io_config ).

    update_data( it_t001  = lt_t001 io_config = io_config ).
  ENDMETHOD.


  METHOD select_data.
    SELECT *
      FROM t001
      WHERE bukrs IN @io_config->mt_r_bukrs
        AND waers IN @io_config->mt_r_waers
      INTO TABLE @rt_t001.
  ENDMETHOD.


  METHOD update_data.
    DATA(lt_t001) = it_t001.

    LOOP AT lt_t001 REFERENCE INTO DATA(lr_t001).
      lr_t001->butxt = io_config->md_butxt.
    ENDLOOP.

    IF io_config->md_test = abap_false.
      UPDATE t001 FROM TABLE lt_t001.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Mit der entsprechenden Technik und einer gewissen Voraussicht sollte es möglich sein, die Schnittstellen sehr klein zu halten und deine Objekte in Zukunft offen für Erweiterungen zu lassen, ohne die Schnittstellen komplett umbauen und erweitern zu müssen.


Enthaltene Themen:
OOABAP OOMethodenschnittstelle
Kommentare (0)

ABAP - Step

Kategorie - ABAP

Heute einmal ein neuer Zusatz für die Schleifen und wie du ihn verwenden kannst. Mit Step hast du die Möglichkeiten Schritte in einer Schleife zu überspringen.

02.09.2022

ABAP OO - Verkettung und Casting

Kategorie - ABAP

In diesem Artikel geht es um Verkettung von Methoden- und Objektaufrufen, weiterhin möchten wir dir den Hintergrund zum Casting erläutern.

20.08.2021

ABAP OO - Data Access Object (DAO)

Kategorie - ABAP

In diesem Artikel schauen wir uns einmal die DAOs an, was du mit ihnen machen kannst und wobei sie dich unterstützen.

23.07.2021

ABAP OO - Konstanteninterface

Kategorie - ABAP

Die Verwendung von Konstanten in der objektorientierten Programmierung gehört zum Standard für die meisten Klassen. Heute zeigen wir dir ein einfaches Beispiel für übergreifende Objekte.

16.07.2021

ABAP OO - Ausnahmeklassen

Kategorie - ABAP

Heute schauen wir uns die verschiedenen Ausnahmeklassen an und wie du selbst eigene Ausnahmeklassen anlegen und verwenden kannst.

09.07.2021