Monday, 2 January 2017

Using chained statements to imitate varargs in ABAP

In other programming languages (like Java for example) there is a concept called varargs for method parameters. Instead of having to build an array by hand you can just pass your elements separated by a comma to the method and the runtime/compiler will make an array for you and pass it to the method. It looks like this:

public void log(String... entries) {
    Arrays.asList(entries).forEach(System.out::println);
}

// Using an array as the actual parameter
String[] entries = {"Log entry one", "Log entry two", "Log entry three"};
log(entries);

// Using varargs
log("Log entry one", "Log entry two", "Log entry three");

In ABAP however there is no concept of varargs. It actually is in conflict with named parameter passing and optional and default parameters. So for the logging method above we would probably write two methods instead, one taking only a single log entry as an argument and the other taking a table of log entries so that the caller does not need to wrap the method call in a loop, like this:

CLASS lcl_logger DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      log IMPORTING iv_text TYPE string,
      log_table IMPORTING it_entries TYPE stringtab.
ENDCLASS.

CLASS lcl_logger IMPLEMENTATION.
  METHOD log.
    WRITE: / iv_text.
  ENDMETHOD.

  METHOD log_table.
    LOOP AT it_entries ASSIGNING FIELD-SYMBOL(<lv_text>).
      log( <lv_text> ).
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

With 7.40 ABAP syntax the log_table-call is not too bad, as you can just initialize the internal table inline using the VALUE statement, like this:
log_table( VALUE #( ( `Log entry one` ) ( `Log entry two` ) ( `Log entry three` ) ) ).

But there is also another possibility which does not need the log_table-method at all. I have never seen it in any ABAP code until I recently randomly saw a code section in an ABAP book where a chained statement was used in a functional method call, which I did not even know was possible. With that you could do something like this:

log(:
  `Log entry one` ),
  `Log entry two` ),
  `Log entry three`
).

This is not technically related to varargs because at compilation the chained statement will just be split up in individual method calls and the method will be called three times. However, the syntax for the call looks similar and there might be some situations where it could be easier to read or maintain than individual method calls or wrapping them in a helper method.

For example returning parameters and expressions using them especially with inline declarations in interaction with chained statements will lead to unexpected behavior.

Here’s a more advanced example using CL_SALV_TREE-methods. One can argue if it increases or decreases readability and maintainability.

mo_object_tree->get_columns( )->get_column(:
  'OBJECTNAME' )->set_visible( abap_false ),
  'COMPONENT' )->set_visible( abap_false ),
  'COMPONENTTYPE' )->set_visible( abap_false ),
  'PARENTCOMPONENT' )->set_visible( abap_false )

No comments:

Post a Comment