Skip to Content
Author's profile photo Jörg Krause

Changing, exporting – why I don’t like them

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.

Exporting parameters

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.

Performance issues

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.

Conclusion

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?

Assigned Tags

      12 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Manuel Hofmann
      Manuel Hofmann

      One could argue does it make sense to use the parameters if an exception is raised? In the end, the method was not able to fulfill its purpose (you raised an exception). So does it make sense to process the parameters? In my opinion no.

      I try too to avoid changing parameter as much a possible, however in the case of exporting i always try to clear them before anything happens.

       

      Author's profile photo Jörg Krause
      Jörg Krause
      Blog Post Author

      However, the value has changed after the exception has been raised. Maybe it is used further on in a different context. With changing / exporting, you have to care about these things, with returning not.

      Author's profile photo Jacques Nomssi Nzali
      Jacques Nomssi Nzali

       

      As Horst Keller once pointed out,

      changing parameters passed by reference are changed immediately, changing parameters passed by value are only returned if the method is left regularly (without exception) via RETURN or ENDMETHOD.

      you can pass a CHANGING parameter by value.

      JNN

      Author's profile photo Jörg Krause
      Jörg Krause
      Blog Post Author

      Yes, you are right. As long as I do not forget ticking the "value" checkbox in a changing parameter, I'm save. On the other hand, with returning, I can't forget it, it's mandatory.

      Author's profile photo Suhas Saha
      Suhas Saha

      On the other hand, with returning, I can’t forget it, it’s mandatory.

      But "Pass-by-Value" has a performance aspect as well. (cf. https://blogs.sap.com/2017/07/30/the-mysteries-of-the-returning-parameter)

      I would give a closer look at the performance when my return parameter is an internal table, which might contain bulk data.

       

      Author's profile photo Jörg Krause
      Jörg Krause
      Blog Post Author

      If you read the blog you mentioned, you will find there that the performance loss you have using returning parameters is about 1/2 percent. The blogger measured the following:

      As you see, the duration of passing a huge data table with returning is almost the same as with exporting. In fact, it was this blog that made me give up the exporting parameters and fancy the returning.

      Author's profile photo Suhas Saha
      Suhas Saha

      The duration of passing a huge data table with returning is almost the same as with exporting.

      I have read the blog but i would take it with a pinch of salt. I would expect the performance to depend on the width of the table-line. The table in example USR02(44 fields in my system) is narrower than say BSEG(393).

      If you see my blog comment, i am all in with using internal tables as RETURNING but i would pay a special eye on the performance.

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      What ABAP methods? LOL 🙂

      It should be just USING and CHANGING, in/out, whatever you call it. The rest is blasphemy. Too many choices, too many problems. Keep it simple, that's what I think.

       

      Author's profile photo Michael Biber
      Michael Biber

      Another option:

      We stated in our development guides that larger pieces of data must be returned using a real reference (REF TO).

      On the other hand this approach has a downside: When does ABAP learn that the result of a method can be dereferenced directly?

      lt_table[] = lr_object->my_method( )->*[].
      Author's profile photo Jörg Krause
      Jörg Krause
      Blog Post Author

      To me, this approach goes exactly in the opposite direction. Working with data references means,  that if you change your data in method A it will change also in method B without being able to understand where the change came from if not searching in all methods where the reference has been used.

      Author's profile photo Michael Biber
      Michael Biber

      I am not sure if I expressed myself correctly. I am not speaking of passing references into a method and change them. I am just talking about the RETURNING parameters. Every caller can be sure to get a fresh data instance when receiving data from a method by a RETURNING parameter.

      Author's profile photo Jörg Krause
      Jörg Krause
      Blog Post Author

      Can you give a code example for that? I'm afraid I am completely confused.