Skip to Content
Technical Articles
Author's profile photo Andrew Barnard

Mind the shadows!

A quick search in your favourite web browser with the phrase “scope in the ABAP programming language” returns a large listing of questions and opinions about the roles and employment future of ABAP programmers. Whereas a similar search with the phrase “scope in the Rust programming language” or “scope in the Java programming language” returns a listing of articles discussing the validity and visibility of types and variables. Whilst the employment future of ABAP developers is a topic worthy of discussion, the apparently not such a popular topic – scoping of variables and types  in ABAP – is the focus of this little blog post.

Within an ABAP program, variables can be defined as attributes of local classes or within methods or procedures like subroutines. These local variables have visibility only within the scope of the local classes or procedures.  Variables defined in the global declaration of an ABAP program have program wide scope and validity. They are typically called global variables.  A similar scoping exists for types in an ABAP program. Types can be defined with local validity within a local class, method or procedure or globally declared in the ABAP program itself.

When it comes to types, we shouldn’t forget about the types that are defined in the (global) repository of the ABAP system. The persistent data elements, structures and tables definitions from which many of our program variables derive their type information. Nor should we overlook global classes – another type of object which can be utilised within our programs as a reference type for variables.

If I ignore the visibility rules of packages, from the perspective of the run of the mill ABAP program, we have three common scoping areas for variables and types. I’ll call them levels – numbered as follows:

  1. Globally defined outside of the program in the system repository, like data elements, types, structures and other programs like global classes
  2. Globally defined in a program
  3. Locally defined in a local class or procedure

At the top of the list – level 1 – we have the objects with the widest visibility, whilst at the bottom we have the objects with the narrowest of validity and visibility. All clear? It seems so, but that which is apparently clear becomes a little murkier when we step into the shadows.

Variable or type shadowing occurs when a variable or type declared within a certain scope has the same name as a variable declared in an outer scope. The key part here is the same name. In ABAP, the rules are pretty simple – a type or variable defined locally overshadows a type of the same name defined in broader scopes – like globally in the program or in the global repository.  In my list above, levels with larger numbers can overshadow types defined on levels with lower numbers.

Since ABAP is a strongly typed language, during compilation the compiler needs to determine the types of all variables. Despite all the places where types can be defined and the opportunity for shadowing, the compiler works it out.

Whilst the compiler is smart – often humans are not so smart – and poor choices in names for types and local classes leads to lots of confusion for humans when trying to work out what is going on.

For those who prefer to read ABAP language than English, a very small example of what I’m talking about. And yes, whilst I’ve changed the code to protect the guilty, it has all the elements of some code I stumbled across this week.

REPORT SAPFZZZ009.
TYPES CAUFVD TYPE AFIH.          
CLASS CL_ABAP_TIMEFM DEFINITION. 
  PUBLIC SECTION.
    CLASS-METHODS SAY_HELLO RETURNING VALUE(RESULT) TYPE STRING.
ENDCLASS.
CLASS CL_ABAP_TIMEFM IMPLEMENTATION.
  METHOD SAY_HELLO.
    TYPES LOCAL_ORDER TYPE CAUFVD.  
    DATA  LOCAL_ORDER TYPE LOCAL_ORDER.
   ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  CL_ABAP_TIMEFM=>SAY_HELLO( ).  
  DATA PM_ORDER_HEADER TYPE CAUFVD.  

I bet at least some of you had a little mental jolt reading the code. I’d suggest such code requires a higher degree of mental effort to work out what is going on than it needs.

So, to ease the burden upon those who will inherit our programs and to keep your friendly code reviewer on your side, I’d encourage you to consider the following tips when writing your programs:

  • Don’t give program or local types the same name as those in the system repository
  • Don’t define local classes in your programs with the same name as those in the system repository
  • And, in all things, value clarity of intention in your code.

Avoid confusion and Mind the shadows!

 

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Frederik Hudak
      Frederik Hudak

      I like the advice in this blog!

      A few tips from my side:

      • In the class definition you can't have a type and a member variable with the same name, so I would suggest to use t_ as a type prefix. tt_ + plural works great for table types.

      DATA local_order TYPE t_local_order.

      DATA local_orders TYPE tt_local_orders.

      • Local types are underused. A local type is often cleaner than a private type, as it is closer to the code.
      • Declaring a semantic type like t_local_order can be useful
        • if the underlying type has a terrible name
        • if the underlying type is expected to change
      • You can trade member variable prefixes for me, which is cleaner as it is a language construct. Names are not enforced by syntax check.
      • It is possible to shadow builtin functions, such as substring. The builtin will then become inacessible within the class scope.
      • One more place where ABAP goes wrong with scoping is inline declarations, you can declare variables inside conditional branches and they will be valid outside them. Forcing yourself to use proper block-scoping should improve your chances on the job market. Then you can branch out into either C# or Java depending on whether you like no_check or static_check exceptions.
      • You can avoid LinkedIn by searching for jobs through SM37
      Author's profile photo Matthew Billingham
      Matthew Billingham

      Why bother with tt for table types?

      Just use

      DATA local_order TYPE t_local_order.
      DATA local_order TYPE t_local_orders.

      I did have a problem with the replace function, when the super class had a replace method! Took me ages to figure out. I asked the super class owner to change their method name.

      Another advantage of local types is that if you then find you want to modularised your code a bit more, you can easily send it to the class definition (when using Eclipse).

      You can avoid LinkedIn by searching for jobs through SM37. 😀

      Author's profile photo Frederik Hudak
      Frederik Hudak

      tt_ is just my personal preference, my head thinks it stands for "table type"

      Author's profile photo Goran Back
      Goran Back

      Obligatory plug for abaplint where you can check shadowed built-in functions: https://rules.abaplint.org/method_overwrites_builtin/