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?

image





    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

image

And do something like

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

    " Handler returns cv_close = 'X' to close SCREEN
    RAISE EVENT zif_eui_manager~pai_event
     EXPORTING
       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.


ZCL_EUI_EVENT_CALLER

   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
        IMPORTING
            sender
            e_row_id
            e_column_id,

Implementation

First you need to know what method you need to call

image

  • 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

image

Instead of such code

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

We call handlers like this

    mo_event_caller->call_handlers(
     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

    mo_eui_alv->mo_event_caller->call_handlers(
     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

For PAI_EVENT interface ZIF_EUI_MANAGER

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

For ON_USER_COMMAND class CL_GUI_ALV_GRID

    " Instead of set handler
    lo_eui_alv->show(
     io_handler        = me

     " If omit map with all (Could be several ON_USER_COMMAND)
     iv_handlers_map   = 'ON_HOTSPOT_CLICK;ON_USER_COMMAND;ON_PBO_EVENT'
    ).

Example in tr. SE38

  • ZEUI_TEST_ALV
  • ZEUI_TEST_SCREEN_02