Technical Articles
Using New ABAP stuff – Method Chaining and CL_SALV_TABLE
Starting with ABAP in 1989, I have experienced a lot of changes in the ABAP language. Once in a while, SAP introduced major changes like:
– Introduction of Function Modules in R/2;
– Use of longer names for ABAP workbench objects. In the past, even in R/3, the length of ABAP program names was limited to 8 positions.
– Introduction of ABAP OO in R/3 4x
– Introduction of the Web Application Server, BSP, HTTP/SMTP support etc in R/3 Enterprise and of Web Dynpro ABAP in later WAS-releases.
As a result, the ABAP language has evolved from a 100% procedural type of programming language to a hybrid language, supporting both procedural and Object Oriented concepts. As of release WAS702, which is not even a major SAP release, an impressive list of major changes has been introduced. You can get a comprehensive overview of all changes via the ABAP Help menu.
This blog will be about one these changes, introduced in 7.0 EHP2, called ‘Method Chaining’, and the way you can use this to reduce the size of your code without compromising readability and thus maintainability.
What’s it al about?
Until recently ABAP still was a verbose programming language, which means that you need a relatively high number of tokens to get something done. Just consider the huge amount of intermediate variables you always need to pass data from one procedure to the next. With the introduction of Method Chaining, the language has become more terse, which means that we now need less tokens to get the same stuff done.
More on Verbose and Terse programming language can for example be found at http://programmers.stackexchange.com/questions/50150/how-to-determine-if-a-programming-language-is-verbose-or-terse
In my opinion, method chaining improves the readability of ABAP code when used properly. However, I know that there are also ABAP-pers who don’t agree with me on this. In this blog I will be using an example using CL_SALV_TABLE to demonstrate how the use of method chaining can decrease the size of your code without compromising its readability.
CL_SALV_TABLE – Before Method Chaining
The CL_SALV_TABLE class was introduced in WAS640 as a new and easier way to implement ALV (interactive) list functionality. Using this class, you only need two statements to display a standard table as an ALV. No field-catalog is needed anymore. In the example below, I have added a few options in order to influence the display and function settings.
DATA: alv_table TYPE STANDARD TABLE OF t001.
DATA: alv TYPE REF TO cl_salv_table,
alv_functions TYPE REF TO cl_salv_functions,
alv_display TYPE REF TO cl_salv_display_settings,
alv_columns TYPE REF TO cl_salv_columns_table,
alv_layout TYPE REF TO cl_salv_layout,
alv_select TYPE REF TO cl_salv_selections.
DATA: st_alv_layoutkey TYPE salv_s_layout_key.
SELECT * FROM t001 INTO TABLE alv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = alv CHANGING t_table = alv_table ).
alv_display = alv->get_display_settings( ).
alv_display->set_striped_pattern( cl_salv_display_settings=>true ).
alv_display->set_list_header( sy–title ).
alv_columns = alv->get_columns( ).
alv_columns->set_optimize( ).
alv_layout = alv->get_layout( ).
st_alv_layoutkey–report = sy–repid.
alv_layout->set_key( st_alv_layoutkey ).
alv_functions = alv->get_functions( ).
alv_functions->set_all( abap_true ).
alv_select = alv->get_selections( ).
alv_select->set_selection_mode( cl_salv_selections=>multiple ).
alv->display( ).
What you see in this example is the need for intermediate variables when setting for example alv functions.
CL_SALV_TABLE – Using Method Chaining
Using Method Chaining, we can get rid of most of the intermediate variables and the separate method calls to get the proper references to ALV attributes like columns or display. By using method chaining in the example below, I was able to reduce the size of the code from 23 to 13.
DATA: alv_table TYPE STANDARD TABLE OF t001.
DATA: alv TYPE REF TO cl_salv_table.
DATA: st_alv_layoutkey TYPE salv_s_layout_key.
SELECT * FROM t001 INTO TABLE alv_table.
cl_salv_table=>factory( IMPORTING r_salv_table = alv CHANGING t_table = alv_table ).
alv->get_display_settings( )->set_striped_pattern( cl_salv_display_settings=>true ).
alv->get_display_settings( )->set_list_header( sy–title ).
alv->get_columns( )->set_optimize( ).
st_alv_layoutkey–report = sy–repid.
alv->get_layout( )->set_key( st_alv_layoutkey ).
alv->get_functions( )->set_all( abap_true ).
alv->get_selections( )->set_selection_mode( cl_salv_selections=>multiple ).
alv->display( ).
My conclusion
This example of using Method Chaining is just one of many that I can think of. Using it in situations where you first need a GET-method to get a reference to an object before being able to SET a specific attribute of that object is, in my opinion, a good use case for chaining.
Usually I'm rather skeptical about OO since many times the code ends up not better than using, say, FMs (and the same FMs are called in the methods). But this is a good example of when "new stuff" would be useful even for hardcore skeptics. 🙂
Thanks for posting!
Hello Ben,
Method is chaining is great way to remove helper variables. In Release 731, you could even add complex calculation, string manipulation etc as part of the method chaining. To ease the debugging, there is a new tab in the Debugger called Auto to display step by step execution and result.
Thanks,
Naimesh Patel
Good Stuff...Thank you for sharing this information
It's a pity there is no WITH-DO command...
This still is not possible:
I'd like to have something like
Following works.
Yes, that works! Thanks for reminding! At least this more looks like parser glitch because there are more closing brackets than opening brackets.
I have started to just define "long text" in global data elements and also in cl_salv_table programs and leave the short and medium ones blank. This way I get one and only one column header which helps my simple male brain function better and the code is a bit less cluttered.
Hello, it's nice to meet you
I'd like to have something like
C#
for(int i = 0; i<columns.count;i++)
{
columns[i]->set_short_text( ' test' )
}