Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Michał_Biegun
Explorer
4,097

In engineering, every solution involves trade-offs—it's about weighing the pros and cons. The same applies to HN, which isn’t all evil. Back in the days, when we just gave up on GO TO instruction (hail to Edsger Dijkstra) and had only 72 characters for one line of code, marking variables as local/global was a way to manage situation, where we use 20 locals and 30 globals within one procedure and it's hard to guess what is what. Limited length of names didn't help either, so all those "ls_" had some significant advantages.

But times have changed. We now have modern IDEs like Eclipse and ABAP OO, allowing us to write smaller, more manageable routines. Most of the limitations that existed in the early days of ABAP are no longer an issue. As a result, the benefits of HN have disappeared, leaving only the drawbacks, which actively harm the quality of code.

Harm #1: It Encourages Laziness and poor Naming

Real life example (just one of many): gt_vbak, gt_vbak2, lt_vbak1, lt_vbak2. These names I had encountered in a > 10k  long report. Trying to make sense of this was maddening. Eventually I decided to rename despite having no access to Eclipse on that system. The new names were:

  • gt_vbak = orders
  • gt_vbak2 = quotations
  • lt_vbak1 = orders_wo_quotation (in one routine, all orders not originating from quotations were extracted and processed)
  • lt_vbak2 = rejected orders -yes sir! Digit 2 in the name didn't indicate quotations, they were also orders 🙂 .

The irony is that these tables weren't even based on the vbak type but were locally defined. So keeping 'vbak' in the name.

I know, nothing stops us from making meaningful names with HN, so gt_partners and ls_partner are possible. And yet almost no one writes gt_partners. What's worse, some create gt_partner and ls_partner. What is gt_partner in this case? It sounds like a table of data for one partner only, but I guess it's not.

To summarise: You could make good names with HN, but practice shows, that no one does. Whereas banning prefixes forces us to spend a minute on creating a proper name. It's not a technical issue. In fact it's a matter of human  nature.

Harm #2: It Makes Code Harder to Read

In the example above, no matter how familiar you are with prefixes (I had 10 years of prefixing ingrained in me), you’ll still mix up lt_vbak2 with gt_vbak2 every few minutes. It’s just impossible not to. These aren’t real words, so we don’t process them efficiently.

Our brains are wired to recognize words based on patterns. If the frist and last letters of a word are correct and the middle letters are slightly jumbled, we can still read it as if it were correct, sometimes without even notciing the errors 😉. This shows that our brains help us read familiar, pronounceable words , but offer no such support for prefixes like lt_, gs_, and so on.

A friend of mine once decided to try coding without prefixes. For the first two weeks, he cursed me and my descendants to the 20th generation, as breaking a habit of 10 years was tough. But after three weeks, he said it felt like seeing clearly for the first time. Code without lt_ reads like a novel - like human language - whereas prefixed code felt like hieroglyphics. Sure, if you’re used to hieroglyphics, you can read them quickly, but it’s still much slower than reading a regular novel.

As Uncle Bob once said, adding prefixes is like adding unnecessary code to the code itself. When reading, my brain first has to decode the prefixes, and only then can it process the ABAP. Writing in plain, human-readable language lets us focus entirely on the ABAP itself.

Harm #3: It Impairs Our Way of Thinking

When using HN, it influences how we use code completion.: I write a code and now I need to get something from table of orders. So I don't bother thinking what was its name - it's enough to type "lt_" and hit ctrl+space.

When I gave up on HN, I had to start using meaningful names (because there was no option to add prefix to the terrible, 4-letter table name). Now, I "search" for variables by their name, not their type. I know I’m looking for a table of customers, so I type "cus" and hit ctrl+Space. After three months of working like this, I found myself improving the clarity of my variable names even further. I even started creating "families" of names, such as orders_rejected, orders_closed, and orders_in_processing, as it helps utilise code completion even further. At the same time code becomes even clearer.

Sticking with prefixes would have never allow me to improve this way.

Harm #4: It Misleads, It Lies

Thousands of times have I seen:

  • lt_kna1, which was actually global.
  • lv_something which was a structure, not a variable,
  • ls_bkpf which was not of a bkpf structure,
  • and many other lies.

This led to a habit where, if scope (l/g) really mattered, I would always check (by double click in SE80 or glimpse on the overview ruler in Eclipse). So I ignore letter l/g - it became a noise for me. The same goes for types - I never trust the letter and I check the type by myself (F2 in Eclipse). This double-check actually saves some time (and nerves).

Honestly, I’d rather have no information at all than false information (the same criticism applies to misleading comments, but that’s another story).

Harm #5: It Increases the Entry Threshold

There is some general agreement in ABAP world, on which prefixes to use...

Oh is there?!? wa_, or ls_? What about mv_ for the "member" attribute in class? What if it's a static? By definition It's not a member, so should we still call it mv_ or maybe sv_?

How about field symbols? When I see <fs_some_data> it makes me fill like this:

Pulp Fiction - Any Of You Pricks Move

I mean come on, didn't you see the angle brackets <>? Are they not enough?

But what about <ls_some_data>? Is it a field symbol, or a structure? What if we agreed on prefixing field symbols, but this one is of any type?

And what about objects? After all, they are all references. So some will call them lr_sth, and some others lo_sth, whereas "lr_" will be reserved only for non-object references (but here you loose information if it's a reference to a variable, structure or a table!)

STOP! Go back to "wa_". Oh my, I don't know if it's local or global. The same with <fs_...>.  I'm so confused 🤕!

Well, you end up with some naming rules and each new member of the team has to learn them and get used to them even though they bring no value. What's weird - prefixes are more required from the freshman than proper naming in general.

Harm #6: It Creates Inconsistent Styles

Because of the reasons above, one person in a program might use wa_ (making it unclear if the variable is local or global), while another uses ls_ or gs_. Some might use it_ (which I think stands for internal table), while others use lt_ or gt_. Then there’s the lr_ vs. lo_ debate. In the end, what we have is not a program, but a riddle.

Nothing forces us to make this mess... except human nature. I’ve seen plenty of programs suffering from MNA (Mixed Naming Arts. 😉  ).

 

Since I have mentioned mixed naming styles I'd like to point out, that it's absolutely essential to follow the existing style (or to rename the whole code). Having two naming styles is always worse than having one, no matter how bad the style is.

What Stops Us From Ditching HN?

Basically, the only thing that holds us from dropping HN is habit. After using it for years, we think it’s easier because it’s all we know.

It takes about 3-4 weeks to retrain your brain, and I guarantee you won’t lose the ability to read old, prefixed code. You’ll still be able to read and write it.

However, giving up HN won’t noticably improve your code unless it’s part of a broader set of changes, including:

  • Meaningful naming (without HN)
  • Small routines (methods)
  • Single responsibility

This short list is just the beginning, but following these three principles alone (along with giving up on prefixes) will significantly improve the quality and maintainability of your code.

What Now, What To Follow?

If not HN, then which style should I follow? If you want some clues, please refer to CleanABAP. It's published as a book and also available on GitHub:

https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md

 

Since I have started the topic, I guess I will continue and elaborate on this short list in next blog posts.

 

25 Comments
UweFetzer_se38
Active Contributor

This! 100%

ziolkowskib
Active Contributor

What Stops Us From Ditching HN?
In many cases it's a local Team Leader or so called Code of Conduct prepared in the good all days of FORMS and SAPScript that enforces HN. Honestly in many cases I do not feel motivated enough to change mindset of some people hence I stick to their rules. And I have the same feelings about <FS> - it makes my eyes bleed. 

radinator
Participant
0 Kudos

In my company we have 2 1/2 programmer: My coworker, me boss and me. Guess who the 1/2 is 😉

Regardless, my coworker and boss all use this wa_ notation while I definitly prefer the lt_ and gt_ version to make clear wether or not we are using a global or local variable. The issue here is that everyone of us 3 is coding int their own little space, barly any situation where I have to maintain the other's code (or vice versa). I tried for 2 years to convince them to abolish the wa_ convention since (as mentioned int he post) it's unclear if the variable is a global one or local.

I have been a fan of HN for as long as I am programming in ABAP (about 5 years now), before that I worked with C# for private stuff and RPG3 & RPG LE/4 for my company (yea the old IBM system, 80 chars per line, 6 char per variables, good times (jkjk)). "Back then" we hadn't have the issue of local vs global (in RPG3, in RPG LE/4 you could have longer names but for what reason? Stripping a,e,i,o and u from Material Numer to MTRL NMR and shortening this to MTRLNR was enough! 😭).

After reading this post I am more inclined to try and reverse back to "speaking variable names" instead of HN. I mean what can I lose? Time? Nah, the worst that can happen is that I don't like non-HN and go back-back to HN.

Thank you @Michał_Biegun for this wonderful insight! May the code you read be clear, concise and understandable and the compiler always obey you(r commands)!

Michał_Biegun
Explorer

@radinatorplease comment here your experiences after 1-2 months from switching to meaningful names. I'm very interested in your impressions.

Jelena_Perfiljeva
Active Contributor

It's been only 9 years since the last Great Hungarian Notation debate on SCN. 🙂

I have to admit I make some exceptions for parameter (p_) and sometimes importing/exporting stuff in the methods. But there is no value whatsoever in lv_, <fs...> and whatever wa is supposed to be.

Sadly, examples in ABAP documentation don't have our back here. It's littered with itab and wa and "JOIN sflight AS a" and other lazy, unreadable code. Would be very nice if someone finally cleaned those up.

P.S. If someone feels oppressed by their local guidelines / senior developers, here is a post for you.

radinator
Participant

@Jelena_Perfiljevayou need to remove the space at the end of the first link to the last HN debate or else user, who open the link, will get an invalid argument error page. Until this: removing the %20 at the end solves the issue for me.

martinc_mb
Participant
0 Kudos

I cannot believe, in our team, how much time has been wasted enforcing stupid HN. At the end of the day, SAP is to blame, as the naming of variables this way was promoted in their documentation. But it adds zero value. The "I need to see what kind of variable this is" argument holds no water. If you struggle to read or understand code because it does not have HN then, I am sorry, the problem is not with the code, buddy.

rosenpetrov
Explorer

tables:
lt_ - local variable table
mt_ - class member variable table
gt_ - global variable table

simple type variables:
lv_ - local variable 
mv_ - class member variable
gv_ - global variable

Ability to distinguish local, class member and global variables is an important one, at least for me.
Although i try to use as little as possible global variables..

Ryan-Crosby
Active Contributor

I have avoided using that terrible notation for several years, but there are a couple of exceptions.  I use c_ for constants (read-only awareness), t_ for tables so I can distinguish lists from normal values or structured values, and there are s_ and p_ for select options and parameters in report screens.  Outside of that I provide meaningful names for what the content would represent within the flow of the program.

 

Regards,

Ryan Crosby

StephanZiemer
Explorer

After more than 25 years of ABAP I strongly resisted the idea of dropping the prefixes. Nonetheless I tried it because some other senior developers said, that they like the cleaner code without the prefixes. So I gave it a try and to my surprise - I don't like prefixes any more! It's 100% as you state: Naming variables takes a bit more time and definately more thought, but the code improves by much more meaningful variable names.

garethquaile
Product and Topic Expert
Product and Topic Expert

To steal the top comment from a stack overflow thread about why we should move away from HN

 

vUsing adjHungarian nnotation vmakes nreading ncode adjdifficult. 😄

Michał_Biegun
Explorer
0 Kudos

@rosenpetrov

1) Why do you need distinction t/v? For example you see such code: LOOP AT items INTO item. From this you clearly see, what is table and what not.

2) If you follow other rules of clean code (the more important ones), you don't need the l/g/m indicators.

Every time you feel a bit lost and you think "hey, I need prefixes to understand the code" you should refactor your code. This thought is a clear sign of code smell, which should be eliminated.

Alwin_vd_Put
Explorer
0 Kudos

Thank you for this nice article about the rationale to not use NH. I am looking forward to your next articles on this topic. I hope they will cover the best practices of Non-HN, because that would help a lot of developers to switch to good descriptive variable names.

In particular, how you can see from the naming whether it is a value variable, structure variable, table type variable, or object reference variable.

rosenpetrov
Explorer
0 Kudos

@Michał_Biegun 

How you distinguish between class member table sales_orders and local table sales_orders ?
mt_ and lt_ gives you immediate sign - local or class member variable, so i know that i'm modifying a local variable and not the class member...

radinator
Participant
0 Kudos

@rosenpetrovIMO if you have trouble distinguishing between a local variable and a class member your problem isn't solved by HN but by choosing better names in general.

Silly example but think about this:
Within a methode, the lifetime of a variable is very short, someone could say it's temporary, so why not use sales_orders for the class member variable and temp_customer_sales for the local one? Yea i know temp_ is basically a malformed HN but I hope you get the idea 😉 .

StephanZiemer
Explorer

Easy way out: Use "me->" if you need to make it clear.

me->sales_orders = sales_orders.

ziolkowskib
Active Contributor

@rosenpetrov 

How you distinguish between class member table sales_orders and local table sales_orders ? mt_ and lt_ gives you immediate sign - local or class member variable, so i know that i'm modifying a local variable and not the class member...

Personally I use me-> or classname=> for accessing class members. 

radinator
Participant
0 Kudos

@StephanZiemerTHIS TBH!

C# uses this, VB.NET uses Me, ABAP has the me keyword

I haven't done OOP ABAP, but I have read some OOP code. Totally forgot about that 😅

UweFetzer_se38
Active Contributor
0 Kudos

Not using HN is only possible in combination with "Clean Code".

"Clean Code" describes the length of a method as "short" (indeed very short!). You shoud see whether a variable is local or a class attribute by simply looking at the code.

METHOD methodname.
  DATA(today) = sy-datlo.
  tomorrow = today + 1.
ENDMETHOD.

 (and we don't have to talk about global variables because you don't need to use them at all).

Michał_Biegun
Explorer

@rosenpetrov 

Naming is a part of clean code. Not using HN is just one of the naming rules. The other, more important, is to name things by their context. So to answer to your question, I need to add the context, so here's the example:

CLASS lcl_quotation DEFINITION.
PUBLIC SECTION.
METHODS get_ordered_value
  RETURNING(result) TYPE p.

PRIVATE_SECTION.
  DATA: orders TYPE TABLE OF REF TO lcl_order. "table of orders, that derive from this quotation
ENDCLASS.

CLASS lcl_quotation IMPLEMENTATION.
METHOD get_ordered_value.
*let's assume, that initially I made summary, but now I need to deduct
*rejected, or not finished orders (example is created now in hurry, so it
*doesn't necessary make sense)
  data: rejected_orders TYPE TABLE OF REF TO lcl_orders.
  LOOP at orders ASSIGNING FIELD-SYMBOL(<order>).
    IF <order>->is_completed() = abap_false.
      APPEND <order> TO rejected_orders.
    ENDIF.
  ENDLOOP.
*later I do calculus and differential equations on rejected orders to see, if 
*customer was happy or not ;)
ENDCLASS.

As you can see, my local context is always something. I either look at rejected orders, or completed orders, or blue orders, or green orders. So I name them accordingly. But if I use HN, I will not think about context - I don't have to. Thinking about context costs some effort. So I call it mt_orders and lt_orders. But who knows what is inside lt_orders? You have to read the WHOLE code to figure it out, whereas variable rejected_orders is self-explanatory, self-documenting and self-commenting.

This is exactly what I meant when I wrote that HN impairs the way of thinking.

Ryan-Crosby
Active Contributor
0 Kudos

@Michał_Biegun word of the day is "context" and good naming provides all the context one needs for solid understanding... great example BTW!

rosenpetrov
Explorer
0 Kudos

Hello guys,
yes  for our own easiness we should use a meaningful names: orders instead of lt_vbak is an example.
Also agree that if we play acc. to the rules we would have a simple and clean methods with not too much source code lines. Someone has posted that about distinguishing class member from local we could use me-> (i have forgot about it using it quite rarely).
I also agree that in one clean code with a usage og mt_ and lt_ there could be quite often that somebody comes and makes changes by using mt_ and lt_ in incorrect manner - pointing not to member and locals.

Patrick_vN
Active Contributor

Interesting read.. though I can't really agree with some of your examples. The main issue with "gt_vbak" is not the HN part for me, it's the 'vbak' part that is misleading. 

So if you're comparing  'gt_orders' with 'orders', then it comes down to the developer guidelines and naming conventions that are agreed upon (or imposed). As long as it is consistent. But I'd say that for an inconsistent developer the result will be inconsistent. HN or not. 

And it's not the HN that misleads or lies, it's the developer writing the code! Using meaningful names wouldn't lie or mislead I guess? But again, in the example I used above, it's the 'vbak' part that is misleading.. the fact that it is a global variable might be interesting to know.

So, yes, guidelines! Code review. Adapted ATC checks (that preferably make sure you cannot transport stuff that doesn't correspond to the guidelines) 
 

 

p_kuhnen
Discoverer
0 Kudos

Ist there an ATC Check available to avoid HN?

radinator
Participant
0 Kudos

@p_kuhneniirc you can set a check in the ATC that checks for the prefixes like lt_ gt_ and so on. If the check finds a variable name matching those prefixes it will tell you and therefore you know the code doesn't adhere to the guideline

Labels in this area