ABAP Quick - CLEAR right
Delete correctly? In this article we want to take a look at when it makes sense to delete and how you can do it effectively.
Table of contents
How should you delete your variables in development these days, do you still have to do it at all and what help can we give you along the way. In this article you will learn a little more and be trained by us to become an extinguishing professional. So sit back and enjoy the article.
Introduction
Sometimes the little things make your life easier or harder when you are looking for mistakes. Besides clearing variables, there are other methods to initialize the data and run into fewer problems in the process. Even with the design of your software, you can eliminate many problems beforehand and increase stability.
Besides directly erasing variable contents, there is also overriding, garbage collector and design of your software that can be considered.
CLEAR
The easiest way to clean up your variables is to simply delete variables, CLEAR, REFRESH and FREE are available for this. However, we only recommend using a statement. REFRESH is obsolete and FREE works in a similar way to CLEAR, which is why the name CLEAR fits best. Here is an example of different ways:
" Clear variable (single)
CLEAR ld_field.
" Clear variable (chained statement)
CLEAR: ls_structure, lo_reference.
" Clear table
CLEAR: lt_table.
" Clear table (with header line)
CLEAR: lt_table, lt_table[].
From simply deleting variables, structures and references to deleting tables and tables with headers.
Hint: The variant of deleting tables with "[]" headers may confuse other developers if it's just a simple table. We therefore recommend carefully choosing the correct variant here, also because source code can be saved.
Global variables
Variables that are defined globally, whether in a class or a report, can lead to errors if they don't have the right value when used or if they weren't deleted properly. In the past, tables and structures to be looped over were often defined globally and most likely used in subroutines. Such processing entails a very high risk, since one never knows whether the variables are still filled correctly at the time of processing.
Local variable
Switching to local variables already reduces this problem and causes problems in at most one method. After exiting the method, the variables are deleted by the system's garbage collector and are initialized again the next time the method is called.
DATA:
lt_table TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
ls_structure TYPE ts_return.
" Loop with predefined variable
LOOP AT lt_table INTO ls_structure.
ENDLOOP.
Inline Declaration
The inline declaration creates the variable where we need it and indicates that this variable is only needed for the loop, for example.
" Loop with inline deklaration
LOOP AT lt_table INTO DATA(ls_inline).
ENDLOOP.
Exporting parameters
Another source of danger are exporting parameters. If the value of the exporting variable is not deleted cleanly, errors can occur depending on the constellation. To do this, let's define the following method:
" Definition
METHODS:
method_with_exporting
IMPORTING
id_param1 TYPE i
id_param2 TYPE i
EXPORTING
ed_result1 TYPE td_char
ed_result2 TYPE i
ed_subrc TYPE i.
" Implementation
METHOD method_with_exporting.
ed_result1 &&= 'Test'.
ed_result2 += id_param1 + id_param2.
ed_subrc = 2.
ENDMETHOD.
To do this, let's do three-step processing and put the method in a DO loop that executes three times. With this combination, we use an inline declaration and define the variable for calling the method.
DO 3 TIMES.
method_with_exporting(
EXPORTING
id_param1 = 1
id_param2 = 2
IMPORTING
ed_result1 = DATA(ld_result1)
ed_result2 = DATA(ld_result2)
ed_subrc = DATA(ld_subrc)
).
ENDDO.
If we now check the result of the variable, we would actually expect a different result. The exporting variables are not initialized after the second call of the method and the old value leads to an incorrect result.
Here you should also clean up the exporting parameters immediately after calling the method; old values from previous processing could still be contained here. The problem can mainly occur with tables if rows are repeatedly appended to the end. A simple CLEAR can fix serious problems here.
METHOD method_with_exporting.
CLEAR: ed_result1, ed_result2, ed_subrc.
ed_result1 &&= 'Test'.
ed_result2 += id_param1 + id_param2.
ed_subrc = 2.
ENDMETHOD.
Methods design
In order to avoid the problem with the exporting parameters, it is worth doing without exporting parameters when designing the method. According to Clean ABAP, the method should only have a few importing parameters and one returning parameter, so the method is considered clean. This circumstance also ensures that we no longer have to think about the CLEAR in the return parameters.
DO 3 TIMES.
DATA(ls_result) = method_with_returning( id_param1 = 1 id_param2 = 2 ).
ENDDO.
If we now call the returning method three times in a row and also use the inline declaration, then we see the correct result after each run with the same logic. We no longer have to delete the variables beforehand and thus save further code, and the call also looks much leaner.
Constructor expressions
As the name already describes, such expressions always create new variables and thus automatically delete the old value from the variable.
Filling
Let's take a look at the following example:
ls_structure-result1 = 'One'.
ls_structure-result2 = 10.
ls_structure-subrc = 1.
INSERT ls_structure INTO TABLE lt_table.
ls_structure-result1 = 'Two'.
ls_structure-subrc = 2.
INSERT ls_structure INTO TABLE lt_table.
The second entry will most likely have an error and the RESULT2 field will have the contents of the previous entry. It is also not clear whether this behavior is desired or whether it is an error. By deleting the variables we can avoid the error:
CLEAR ls_structure.
ls_structure-result1 = 'One'.
ls_structure-result2 = 10.
ls_structure-subrc = 1.
INSERT ls_structure INTO TABLE lt_table.
CLEAR ls_structure.
ls_structure-result1 = 'Two'.
ls_structure-subrc = 2.
INSERT ls_structure INTO TABLE lt_table.
However, we still write quite a lot of code and we could reduce that further without having to pay attention to the CLEAR. For this we use a constructor expression directly and save the variable, but also some typing:
INSERT VALUE #(
result1 = 'One'
result2 = 10
subrc = 1
) INTO TABLE lt_table.
INSERT VALUE #(
result1 = 'Two'
subrc = 2
) INTO TABLE lt_table.
Loop
In loops we mostly work with mappings and data assignments to process the data. Before you work with the working structure, you should first initialize it with a CLEAR. You can do this at the end of the loop or at the beginning. We recommend deleting at the beginning of the loop, from reading order when looking for errors, one would first check if the structure was properly initialized.
LOOP AT lt_table INTO ls_line.
CLEAR ls_structure.
ls_structure-result1 = ls_line-result1.
ls_structure-result2 = 2.
ENDLOOP.
Here, too, you can save the CLEAR if you create or fill the variable with a constructor expression:
LOOP AT lt_table INTO ls_line.
ls_structure = VALUE #(
result1 = ls_line-result1
result2 = 2
).
ENDLOOP.
Full example
Finally, the complete example to try it out yourself or adjust it in your own system:
CLASS zcl_bs_demo_clear_right DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES:
td_char TYPE c LENGTH 20,
BEGIN OF ts_return,
result1 TYPE td_char,
result2 TYPE i,
subrc TYPE i,
END OF ts_return.
METHODS:
method_with_exporting
IMPORTING
id_param1 TYPE i
id_param2 TYPE i
EXPORTING
ed_result1 TYPE td_char
ed_result2 TYPE i
ed_subrc TYPE i,
method_with_returning
IMPORTING
id_param1 TYPE i
id_param2 TYPE i
RETURNING VALUE(rs_result) TYPE ts_return,
simple_clear,
global_variable,
constructor_expressions.
ENDCLASS.
CLASS zcl_bs_demo_clear_right IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
simple_clear( ).
global_variable( ).
DO 3 TIMES.
method_with_exporting(
EXPORTING
id_param1 = 1
id_param2 = 2
IMPORTING
ed_result1 = DATA(ld_result1)
ed_result2 = DATA(ld_result2)
ed_subrc = DATA(ld_subrc)
).
ENDDO.
DO 3 TIMES.
DATA(ls_result) = method_with_returning( id_param1 = 1 id_param2 = 2 ).
ENDDO.
constructor_expressions( ).
ENDMETHOD.
METHOD simple_clear.
DATA:
ld_field TYPE i,
ls_structure TYPE ts_return,
lt_table TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
lo_reference TYPE REF TO zcl_bs_demo_clear_right.
" Clear variable (single)
CLEAR ld_field.
" Clear variable (chained statement)
CLEAR: ls_structure, lo_reference.
" Clear table
CLEAR: lt_table.
" Clear table (with header line)
CLEAR: lt_table, lt_table[].
ENDMETHOD.
METHOD global_variable.
DATA:
lt_table TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
ls_structure TYPE ts_return.
" Loop with predefined variable
LOOP AT lt_table INTO ls_structure.
ENDLOOP.
" Loop with inline deklaration
LOOP AT lt_table INTO DATA(ls_inline).
ENDLOOP.
ENDMETHOD.
METHOD method_with_exporting.
CLEAR: ed_result1, ed_result2, ed_subrc.
ed_result1 &&= 'Test'.
ed_result2 += id_param1 + id_param2.
ed_subrc = 2.
ENDMETHOD.
METHOD method_with_returning.
rs_result-result1 &&= 'Test'.
rs_result-result2 += id_param1 + id_param2.
rs_result-subrc = 2.
ENDMETHOD.
METHOD constructor_expressions.
DATA:
lt_table TYPE STANDARD TABLE OF ts_return WITH EMPTY KEY,
ls_line TYPE ts_return,
ls_structure TYPE ts_return.
CLEAR ls_structure.
ls_structure-result1 = 'One'.
ls_structure-result2 = 10.
ls_structure-subrc = 1.
INSERT ls_structure INTO TABLE lt_table.
CLEAR ls_structure.
ls_structure-result1 = 'Two'.
ls_structure-subrc = 2.
INSERT ls_structure INTO TABLE lt_table.
INSERT VALUE #(
result1 = 'One'
result2 = 10
subrc = 1
) INTO TABLE lt_table.
INSERT VALUE #(
result1 = 'Two'
subrc = 2
) INTO TABLE lt_table.
LOOP AT lt_table INTO ls_line.
CLEAR ls_structure.
ls_structure-result1 = ls_line-result1.
ls_structure-result2 = 2.
ENDLOOP.
LOOP AT lt_table INTO ls_line.
ls_structure = VALUE #(
result1 = ls_line-result1
result2 = 2
).
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Conclusion
As you can see, deleting is not necessarily difficult, it just depends on the right perspective and how you deal with the topic of software architecture or software design. We hope the tips have helped you to understand the topic again and you take something with you for your daily work.