Do you use changing and exporting parameters in your ABAP methods? I did it a long time. But I’m cured. It all began, when I startet to consider functional programming style (see this excellent blog ). It lead me to avoid changing variable values after having set them once.
Changing: A simple example
class lcl_app implementation. method main. data ls_line type gty_s_line_to_change. ls_line-field1 = p_field1. ls_line-field2 = `Value 2`. ls_line-field3 = `Value 3`. try. change_field2( changing cs_line = ls_line ). cl_demo_output=>display( ls_line ). catch lcx_excpt. cl_demo_output=>display( ls_line ). endtry. endmethod. method change_field2. cs_line-field2 = `Value 2 changed`. if cs_line-field1 = `Oh no!`. raise exception type lcx_excpt. endif. endmethod. endclass.
In the above code, a changing parameter is used in method change_field2. This method changes one of the fields in the structure passed by changing.
What happens when an exception occurs? Since the change of FIELD2 is done before the RAISE, the field has changed even if the method was interrupted by the exception. If I run this program and put “Oh no!” in the parameter on the selection screen, I get this output:
A better way to achieve this could be:
methods: change_field2 importing is_line type gty_s_line_to_change returning value(rv_res) type string raising lcx_excpt. (...) class lcl_app implementation. method main. data ls_line type gty_s_line_to_change. ls_line-field1 = p_field1. ls_line-field2 = `Value 2`. ls_line-field3 = `Value 3`. try. data(ls_line_changed) = value #( base ls_line field2 = change_field2( ls_line ) ). cl_demo_output=>display( ls_line_changed ). catch lcx_excpt. cl_demo_output=>display( ls_line_changed ). endtry. endmethod. method change_field2. rv_res = `Value 2 changed`. if is_line-field1 = `Oh no!`. raise exception type lcx_excpt. endif. endmethod. endclass.
In this case, you get:
Another issue with changing parameters is that they do not allow using “data(var)” declarations.
Well, I really like the functional form of methods which allows to make chainings:
zcl_queue_processor=>process( zcl_queue_provider=>get( ) ).
So, if it comes to several exporting parameters, I tend to create a structure containing all the values I want to get from my method so I can create the method using a return parameter.
Another annoying thing is that exporting parameters that are passed by reference behave exactly as changing parameters. They keep the value of the passed variable if they are not changed in the called method. This is why the extended syntax check throws a warning when you do not initialize them at the beginning of the method.
Since ABAP knows how to “lazy copy”, i.e. to keep a reference on a copied value until the copied one changes, the disadvantage on performance using the value-based RETURNING par are not too huge. However, when it comes to large tables that are to be changed afterwards, I fall back to a reference EXPORTING var.
All this made me set up a personal programming style rule:
“Whenever possible, use only importing and returning parameters in methods”
What do you think about it?