Skip to Content

Consider the following problem.

We are processing some data in SAP and need to retrieve the text of some domain fixed values (the texts are held on table DD07T). We know the name of the domain (we wrote the program after all) and we know the value. Also being good ABAP developers we want to write efficient, modular code.

To write database efficient code we should buffer the lookup data rather than read it each time from the database, and to make it modular we should put our data retrieval code in a subroutine.

Buffering the data is easy enough we just need an internal table which contains;

domain name
domain value
domain text

So, each time we need some domain texts we can call a subroutine which looks at the above internal table for our domain name and value and reads the text value. If it isn’t there we can read the database and store the result in our internal table in case we need it next time.

But there is a problem, where do we declare our internal table? We can make it global, but being good programmers we know that global variables are bad practise. If the internal table is local to the subroutine it will be cleared each time the subroutine ends. We need some kind of “halfway house” whereby the internal table is local to our subroutine and retains its values for the lifetime of the program.

Luckily, ABAP has the keyword STATICS, which provides just this sort of functionality. Static variables are local to a subroutine but retain their values for the lifetime of the program. All we have to do is declare our internal table with the keyword STATICS rather than DATA and we now have an internal table which is not cleared when the subroutine ends but when the program finishes.

Right, enough theory lets have a look at a proper working example of a subroutine using only local and static variables to completely encapsulate the data.

FORM read_dd07t USING value(p_domain) TYPE domname value(p_code) TYPE domvalue_l CHANGING value(p_text) TYPE ddtext. * declare our working storgage TYPES: BEGIN OF t_dd07t, domain TYPE domname, code TYPE domvalue_l, text TYPE ddtext, END OF t_dd07t.   DATA: l_index TYPE sytabix, wa_dd07t TYPE t_dd07t.   * this is our internal table we are using as a buffer STATICS: itab_dd07t TYPE STANDARD TABLE OF t_dd07t.   * check and see if we have retrieved this value before. READ TABLE itab_dd07tINTO wa_dd07t WITH KEY domain = p_domain code = p_code BINARY SEARCH.   IF sy-subrc NE 0. * no so we need to read it from the database * sy-tabix holds the line in the internal table at which the data * would reside if it was there so we know where to place our value * when we find it. l_index = sy-tabix. * read the data from the database SELECT SINGLE domname domvalue_l ddtext INTO wa_dd07t FROM dd07t WHERE domname = p_domain AND ddlanguage = sy-langu AND as4local = 'A' AND as4vers = '0000' AND domvalue_l = p_code.   IF sy-subrc = 0. * place it where it should go INSERT wa_dd07t INTO itab_dd07t INDEX l_index. ENDIF. ELSE. * possibly put in some default values to prevent * multiple hits on the database ENDIF. * return our found text p_text = wa_dd07t-text. ENDFORM.

Static variables provide a tidy solution to some particular problems, especially when it comes to buffering data. It is not a new concept (they were available in 4.0b) and one that I don’t seem to see many ABAP developers use either.

There is one area where they cannot be used however, instance methods of classes, but you can use them in class methods.

To report this post you need to login first.

10 Comments

You must be Logged on to comment or reply to a post.

  1. John Patterson
    hey Nathan,
    Nice article, I share you thoughts on the overuse of global variables and like to use statics in routines which read single values from tables.

    Just trying to get my head around the syntax in your example.

    Correct me if i am wrong i dont have a system at hand.

    Using READ TABLE with BINARY SEARCH if no entry is found SYST-TABIX will be the total number of lines  (n) or (n+1). INSERT at INDEX (n), will append the value to the end. Without a SORT of the itab the BINARY SEARCH (divide and conquer) will be inefficient in large volumes.

    (0) 
    1. Peter Inotai
      >Without a SORT of the itab the BINARY SEARCH (divide and conquer) will be inefficient in large volumes.

      My experience BINARY SEARCH without sorting, that it is not inefficient, it just simple doesn’t find the correct value in the internal table even if it’s there.

      (0) 
      1. Nathan Jones Post author
        In the above example, when I do the binary search, it stops reading the table at the line where it expects to find the value I am looking for (I am only looking for one entry in the table). At this point sy-tabix is set to where the entry should be in the internal table (if it existed). So I can insert my found value at this point. The result is that the table is built up sorted rather than just appended to the end, so there is no need to do a sort.
        It looks a bit weird but if you run this in the ABAP debugger you can see what I mean.
        (0) 
    2. Nathan Jones Post author
      Hi Jasper,
      In the above example sy-tabix points to the row in the internal table where the entry would be if it existed, not the end. So you can use this value to add the entry in at the right place, rather than adding it at the end and doing a sort.
      (0) 
  2. Peter Inotai
    Hi Nathan,

    Thanks for this info about STATICS. I never used it, and actually I didn’t really see it in SAP standard programs either.
    For me it’s strange to have this kind of declaration, that it’s not global, and not local either.
    Looking forward for further weblogs about similar topics.
    Regards,
    Peter

    (0) 
  3. H. Senden
    hi,

    i’ve read your article and it’s very interesting. I have never used STATICS, and i have seldom see it in my 8 years of abapping.

    But i’m curious about your statement ‘but being good programmers we know that global variables are bad practise’. Why ?

    regards,
    Hans

    (0) 
    1. Nathan Jones Post author
      I guess the reason I think that global variables are bad is because you have little control over them. If you are writing a large program it becomes very difficult to track where variables are being used and as a result accidentally change them, leading to unexpected results. On a personal level, I find programs where there are a lot of global variables difficult to maintain. Also coming from a Visual Basic background global variables led to a lot of problems. So this methodology carried over to my ABAP programming too.
      Being a realist, there are situations where you have to use global variables, but I try to keep them down to a minimum.
      (0) 
    2. Tobias Trapp
      Hi Hans,

      from a theoretical point of view I suggest you to read “W.A. Wulf, M. Shaw (1973) Global Variables Considered Harmful. SIGPLAN Notices 8:80-86.”

      Unfortunately ABAP forces us to use global variables from time to time. In my opinion they are error-prone. Let me give some examples:
      1.) Function Groups with memory in Top-Includes have the problem that their state is hard to control. Just imagine that there are lots of calls that change those variables – perhaps an application changes the state without your knowledge… In those case objects are the better choice, at least they have a defined status when they are created in contrast to function groups that are “created” exactly once.

      2.) Static variables have just the problem: A local variable is much more simpler to understand because it will be initialized each call.

      So avoiding global variables is a way to reduce complexity of your programs. In my opinion you should do whenever it is possible.

      Regards,
      Tobias

      (0) 
  4. Kenneth Moore
    I believe your program example of buffering a table to reduce db reads could also be achieved using CONTEXTS (tcode SE33 – also a little known/used ABAP gem).
    (0) 

Leave a Reply