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
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
- 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
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