Link Search Menu Expand Document

Loose coupling through handlers

   Sometimes OOP can complicate the program structure quite a lot.
If you do not go into the jungle of design, inheritance, design patterns, lambda expressions and other smart and complex things, often you just need to call the method, which is implemented in a completely different place, thereby splitting the code into smaller parts that are not tightly coupled.
To do this, ABAP has two main mechanisms for weakly binding classes to each other interfaces and events.
But how not to complicate your life with inheritance and interfaces and other OOP goodies?


    Interfaces are a very flexible tool for breaking code into logical blocks, which allows you to make code less connected, unlike classes.
But their implementation in ABAP, in terms of writing code, is quite verbose and not always convenient. Also, the fact that you need to implement each method in the interface (unless it is a testing class) introduces additional restrictions on their use.

For example, if you have an interface for managing screens, you need to implement both PAI and PBO methods.
If you do not need a PBO, you make it empty and then write to ATC that it is needed (so-so pleasure)

Then for flexibility you can declare them events


And do something like

    " Send container & current screen number
    RAISE EVENT zif_eui_manager~pbo_event
       io_container = io_container
       iv_dynnr = sy-dynnr.

    " Handler returns cv_close = 'X' to close SCREEN
    RAISE EVENT zif_eui_manager~pai_event
       iv_command = sy-ucomm
       cv_close = REF #( lv_close ).

But what if you need to trigger an event of another class?
For example, make an event call from a local class (Class relevant to local definitions) when it implements part of the logic of a global class.
RAISE EVENT can only be called in its own class.

Or for example, if you have a wrapper on ALV and you want to forward the event from CL_GUI_ALV_GRID to another place, then catch for example on_double_click, and then delegate execution to another class.


   One simple solution is to call the event handler method via dynamic call.
Those handler descriptions can be presented as an interface with a method that can be called via CALL METHOD with PARAMETER-TABLE.

When the code contains a description of the called method, we can call it dynamically by knowing its signature

      on_hotspot_click FOR EVENT hotspot_click OF cl_gui_alv_grid


First you need to know what method you need to call


  • IO_HANDLER - An object whose method needs to be called
  • IV_HANDLERS_MAP - If you have several on_double_click handlers for different ALVs, you need to specify the method name
  • IV_FIRST - Call first? RAISE EVENT does not guarantee call order
  • IV_ACTIVATE - Activate / Deactivate

And then it remains just to call the event handlers using CALL_HANDLERS


Instead of such code

    " Handler returns cv_close = 'X' to close SCREEN
    RAISE EVENT zif_eui_manager~pai_event
       iv_command = sy-ucomm
       cv_close = REF #( lv_close ).

We call handlers like this

     iv_of_class     = 'ZIF_EUI_MANAGER'
     iv_for_event    = 'PAI_EVENT'
     iv_param_nam_00 = 'SENDER'          iv_param_val_00 = me
     iv_param_nam_01 = 'IV_COMMAND'      iv_param_val_01 = iv_command
     iv_param_nam_02 = 'CV_CLOSE'        iv_param_val_02 = lr_close ).

We delegate on_double_click like this

     iv_of_class     = 'CL_GUI_ALV_GRID'
     iv_for_event    = 'DOUBLE_CLICK'
     iv_param_nam_00 = 'SENDER'          iv_param_val_00 = sender
     iv_param_nam_01 = 'E_ROW'           iv_param_val_01 = e_row
     iv_param_nam_02 = 'E_COLUMN'        iv_param_val_02 = e_column ).

If you read up to here and understood the main idea, I shake your hand at a distance

As a result, you can install handlers (or callback methods) through 1 parameter io_handler which has a description of all the necessary handlers


 " Handle of PAI_EVENT
 CHECK mo_screen->show( io_handler = me ) = 'OK'.


    " Instead of set handler
     io_handler        = me

     " If omit map with all (Could be several ON_USER_COMMAND)

Example in tr. SE38