Local declaration obscuring a global variable of same name

Viewed 564

Today, I came across a declaration-dilemma situation in an old code.

Consider the following snippet:

REPORT ZPROGRAM.

DATA: v_data TYPE field.

FORM code_block.
  SELECT SINGLE datum FROM db INTO @v_data WHERE field = @value.
  SELECT SINGLE datum FROM db INTO @DATA(v_data) WHERE field = @value.
ENDFORM. 

This code holds no error.

Now, the first select statement retrieves the data (sy-subrc = 0) but V_DATA is not populated with the data. I expected V_DATA to reflect the data since it is a global variable at this point.

Does the inline declaration of V_DATA obscure its global definition since both variables are of the same name? But why does it happen since the inline declaration happens after the global variable's visibility?

2 Answers

The answer seems "much" more complex than what I thought initially.

My test report is ZTEST:

REPORT ztest.

DATA: v_data TYPE field.

FORM code_block.
  v_data = 'A'.                           " <==== affects the global variable
  CONCATENATE 'B' 'b' INTO DATA(v_data).  " <==== affects the local variable
ENDFORM.

START-OF-SELECTION.
  PERFORM code_block.

I debug these 2 variables (using the backend debugger):

  • V_DATA, to see the local variable
  • (ZTEST)V_DATA, to see the global variable

I see these values while debugging step by step:

Right after execution of this line          V_DATA      (ZTEST)V_DATA
 v_data = 'A'.                                          A
 CONCATENATE 'B' 'b' INTO DATA(v_data).     Bb          A

It's the same if you use this code:

DATA: v_data TYPE field.

FORM code_block.
  v_data = 'A'.                     " <==== affects the global variable
  DATA: v_data TYPE field.
  CONCATENATE 'B' 'b' INTO v_data.  " <==== affects the local variable
ENDFORM.

START-OF-SELECTION.
  PERFORM code_block.

From the ABAP documentation on DATA(...):

The declared variable is visible statically in the program as of DATA(var) and is valid in the current context. The declaration is made when the program is compiled, regardless of whether the statement is actually executed. [...]

A valid statement with an inline declaration of a variable can generally be interpreted as a short form for a declaration statement used as a direct prefix.

DATA var TYPE ...
... var ...

Deviations from this rule occur only if an identically named data object of a more global context is used in the same statement. This is still valid in the statement and is only hidden after the statement.

To compile that a bit: An identifier refers to the data object of a more global context until the DATA(...) declaration is reached. From that point onwards, the identifier refers to the inline declared variable. The FORM statement is what introduces a new context.

That said, shadowing is generally a bad practice acording to the naming guidelines:

Choose program-internal names that cannot be confused with ABAP words or other declarations. In addition, a local name must not obscure a more global name

Related