Fanning the Flames: Prefixing Variable/Attribute Names
Trigger Warning: This blog will probably annoy a number of people. It’s been lurking in the back of my mind for some time now, originally inspired by Ralf Wenzel‘s article Hungarian beginner’s course – a polemic scripture against Hungarian Notation. Among others, I wouldn’t be too surprised to receive critical comments from Matthew Billingham in particular – but then again, maybe not. As Tolkien has put it a long time ago, “So many strange things have chanced that to learn the praise of a fair lady under the loving strokes of a Dwarf’s axe will seem no great wonder.” I figured I might as well give it a try, even though it might spoily my birthday festivities.
To cut to the point: I use prefixes for variables and parameters myself, and I encourage people to use a consistent prefix system throughout their code. In my experience, a sensible naming scheme for variables does help developing and maintaining ABAP code. I don’t for a moment believe that I will convince anyone who doesn’t want to accept that, but I do believe that in this discussion, there are a number of arguments that are too easily forgotten or cast aside. I’m well aware of the fact that this subject is guaranteed to trigger a lively – hum – discussion, so I will try to keep the tone a bit more formal and a little less emotional than Ralf did in his post. (To be fair – his trigger warning is in the title as well as the introduction.)
Perhaps, first and foremost – what is the prefix system I use? It boils down to a combination of one or two letters, an underscore and a sensible name for the variable. I’ll focus on the assembly of the prefix here, since that’s what the ‘hungarian notation’ discussion is about – whether you want to name your variables according to the dictionary structures or rather have some ‘english’ name is another discussion.
The first letter designates the origin or scope of the variable of parameter:
- class members:
- g = instance attribute
- s = static attribute
- methods and (where applicable) function modules:
- l = local variable
- i = importing parameter
- e = exporting parameter
- c = changing parameter
- r = returning parameter
- programs, function groups
- g = global variable
- p = PARAMETERS (report only)
The second letter distinguishes between the data types:
- (none) – elementary data type
- s = structure
- t = internal table
- r = reference
For WebDynpro coding, I use a slightly different notation – basically because I’m too lazy to to through the generated code and adapt it all:
- v = elementary data type (WebDynpro coding since that’s the default in the generated code)
- o = object reference (WebDynpro)
- r = data reference
Exceptions and inconsistencies I haven’t overcome yet:
- so_ = SELECT-OPTIONS
- co_ = constants
- no prefix for public read-only attributes of persistence classes
- no prefix for constants in “enum interfaces” that only contain constants
- TABLES – hello, dynpros! – for structures EXCLUSIVELY, NEVER for transparent tables, same name as the structure
So we get, for example
- gt_foo in a class – that would be an instance attribute that is an internal table
- ls_bar – a structured local variable
- ir_baz – an importing reference parameter
For FIELD-SYMBOLS, I tend to use the same notation, so you’ll see stuff like <ls_foo> or <lr_bar> in my code. Since I tend to avoid global FIELD-SYMBOLS, I could omit the ‘l‘, but decided to keep it for simplicity of the ruleset.
To sum it up: nothing too special here. I don’t claim to have invented this prefix system, only adopted and adapted it slightly – although it’s so generic that probably hundreds of developers around the world use either this system or something very similar. It’s slightly more verbose than the scheme presented by Kai Meder in ABAP Modern Code Conventions, but I believe that the differences do justify an extra character.
Before discussion the advantages and disadvantages in detail, I would like to point out a simple and important fact that appears to be overlooked in many discussions: There is no perfect life. There is just life. We have to make do with what we have, and while we can (and should!) always aspire to refine our skills and improve ourselves as well as our environment, there are shortcomings, deficiencies and historically-explainable-but-nonetheless-ugly-kludges that we just have to deal with. Dreaming of a world without global variables, methods no longer than (insert number here) lines of code and pure object orientation may be an enjoyable pastime, but it doesn’t get the job done. The world is out there, and it contains loooooong methods (many of which started out fairly short and grew through years of maintenance by many hands and a lack of refactoring), insanely complex systems and a weird mix of object-oriented and procedural programming, so we have to deal with stuff like that on a daily basis.
We also have to deal with another important fact: Humans make errors. Even the most intelligent and experienced developer will eventually produce a bug (other blog authors and moderators excepted, of course). Since a naming convention is of no use whatsoever to the maching, it has to be optimized to support the human in front of the machine. Ideally, it should aid in understanding the code that is already present and prevent coding errors wherever possible – or at least make them more obvious. So let’s take a look at some common mistakes and how the naming conventions above aid in preventing or at least spotting these.
Let’s start with a common controversy – why use prefixes for local and global variables at all? There are really two arguments that make me recommend using the prefixes ‘g‘ and ‘l‘ respectively, despite many notable voices arguing against their use. First off – shadowing and name masking. These concepts exist in many programming languages, and I have yet to find a real-world application that does not involve a decent amount of sadism towards the poor souls who have to maintain the code afterwards. From my experience, wherever you see variable shadowing actually happening outside of a programming class, something has usually gone south when refactoring or maintaining the code. Variable shadowing produces particularly nasty bugs that can easily take hours or even days to hunt down. Spliting the namespace into distinct partitions for global and local variables neatly solves that problem – if all class attributes start with ‘g‘ (or ‘s‘) and all method-internal variables start with ‘l‘, shadowing won’t ever be a problem. Other languages cope by adding compiler warnings and smart IDE extensions to help the developer spot variables shadowing each other, which is just another workaround for the same problem, and one we don’t have yet (the last time I checked, even the splendid ATC didn’t warn about shadowed variables).
The second argument for “scope prefixes” I’d like to present is related to the counter-argument “variables are always local, and who get’s to say what’s called global in an object-orientated aplication anyway?” It certainly isn’t easy to answer the latter question, but it helps to approach the issue from a different angle: When I change the contents of that foo thingy over there – then what is the scope (or lifetime, if you prefer) of that change? Am I only affecting the execution context of the method I’m currently in, and whatever I change gets discarded when the method is processed anyway – or am I permanently changing the state of the current instance, or even the entire class? You may want to call these changes “local” and “global”, for want of a better name. Of course, this can be easily determined with a simple double-click, but it’s much easier to write and maintain code if you’ve got that information embedded in the identifier. If you use this consistently, especially as an entry-level programmer, you will find that after a time, using something prefixed with ‘g‘ will start to feel slightly awkward – should this really be global, do I need this anywhere else, can’t I just make this a local variable? – whereas accessing something prefixed with ‘s‘ outside of some specially designated factory methods will set of alarm bells at once just by reading it. I’ve seen many bugs that ultimately could be traced back to an accidental modification of an attribute value (often after an improperly executed refactoring operation), and again, these bugs are really hard to find because they usually only surface much later in the application, and even then only under particular circumstances.
Now for the data type designator – what’s the point in distinguishing between elementary fields, structures, tables and references? Convenience, mostly, but there are a few cases where these prefixes really can help you spot problems. ABAP has a history of peculiar conversion rules, and the one I’m after here is the conversion between flat structures and single fields. Let’s assume you’re coding a data object for some translateable entity (something with a separate language-dependent table that contains the translateable parts of the object), and you’re keeping the text in an atribute named description. Some day you note that you’ve forgotten to add an accessor method for that, so you write a getter that returns a STRING, something as simple as r_result = description. Clean and obvious – until you notice that your application displays ‘100DEFoobar’ instead of ‘Foobar’. Whoops. Looks like description wasn’t only the text, but you decided to store the entire text table entry instead (which makes perfect sense, especially if you’ve got multiple translateable fields). If you had named that attribute gs_description, you would have noted that immediately and prevented that mistake. Now this is an easy example, but I’ve seen this error happen to experienced developers in large applications, and again, it takes time and patience to hunt down that unwanted client number in the outbound message stream.
With internal tables, this kind of conversion error will not occur, but there’s another quirk in the ABAP syntax that virtually every newbie has to master. Consider the following two examples:
DATA: sflight TYPE TABLE OF sflight.
” somehow, magically, fill that table with some values
LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).
” some condition, don’t care, whatever…
DELETE TABLE sflight FROM <sflight>.
ENDLOOP.
as opposed to
DATA: sflight TYPE TABLE OF sflight.
” somehow, magically, fill that table with some values
LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).
” some condition, don’t care, whatever…
DELETE sflight FROM <sflight>.
ENDLOOP.
Now granted, that’s taking it to the limits, but the experienced ones among you will know how inventive the inexperienced among you can get when introduced to ABAP. I might have turned that into another trapdoor article, but just to reiterate: the first example will modify the internal table while the second example will actually kill selected contents of the database table. The issue here isn’t only that this will be dangerous for the application data – bugs like these are usually so catastrophic in their results that they tend to be found early on – but that it is much harder to determine the intent of the developer and pinpoint the bug. Now let’s compare this to a prefixed version:
DATA: lt_sflight TYPE TABLE OF sflight.
” somehow, magically, fill that table with some values
LOOP AT lt_sflight ASSIGNING FIELD-SYMBOL(<ls_sflight>).
DELETE TABLE lt_sflight FROM <ls_sflight>. ” OK – we’re modifying the local table
” contents here
DELETE TABLE sflight FROM <ls_sflight>. ” syntax error: The field “SFLIGHT” is
” unknown, but there is a field with
” the similar name “LT_SFLIGHT”.
DELETE lt_sflight FROM <ls_sflight>. ” ATC complains about “Non-numeric index
” access on internal table”
” and suggests correct variant above.
DELETE sflight FROM <ls_sflight>. ” OK – changing the database contents
ENDLOOP.
Also, after a while, typing LOOP AT lt_ followed by Ctrl+Space becomes a habit, and the code completion will present only the local tables – without robbing you of the flexibility to simply type LOOP AT <Ctrl+Space> and still have access to the full list of options.
All things considered, prefixes for variable names aren’t as bad as some articles make them. Prefixes are a workaround, a compromise between what we have, what we can get, what we need and most importantly what we don’t want. If you’ve ever ran into any of the bugs I mentioned above, either in your own code or someone else’s, you know what I’m talking about. If you haven’t (yet?), still please consider the junior members of your team and the people who succeed you and have to maintain your code. Someone may be very grateful for those few extra characters that really take no time either typing or reading.
I have encountered the "shadowing" problem where an old program has OK_CODE defined as a global variable, also as a parameter of a given routine, and also as a local variable inside that routine. That was fun.
I have also come to grief passing in an entire structure when I wanted a single field in that structure. That could be blamed on the name of the structure not indicating in any way that it contained more than one piece of information. And that fact that the SAP compiler does not care( unless some of the fields are characters and some are numbers).
That said, I am currently going through a bunch of OO code, dropping all the prefixes.
History has shown this to be a very emotive subject indeed and I am sure you will get a boat load of responses.
DATA: lo_cat TYPE REF TO zcl_cat,
lo_pigeons TYPE REF TO zcl_pigeons.
CREATE OBJECT lo_pigeons.
CREATE OBJECT lo_cat.
lo_cat->put( among the = lo_pigeons ).
Or would that read better without the LO_
Or am I dealing you a LO blow?
Well, to each his/her/their own taste of "fun", sounds fair to me. Now that you mention the OK_CODE, I vaguely remember seeing shadowing issues more often when digging through legacy dynpro coding (where MODULES don't create their own scope, which novices frequently don't know)...
LO and behold, there's the discussion level I anticipated 🙂
Hi, my name is Lars and I prefix variables.
From my point of view there is a tradition within the ABAP world to prefix variables.
Just like the Java world where there is a tradition to UpperCamelCase class names, or suffix interface implementations with 'Impl', and C# prefixes interfaces with 'I' instead. 😕
So I say just stick with it, no matter if it's good or bad, changing tradition is difficult.
Another thing, in ABAP all keywords are also allowed as variable names, prefixing helps improving the readability a bit.
Shadowing variables: I've hacked together a check for ATC/SCI, see https://github.com/larshp/abapOpenChecks/wiki/ZCL_AOC_CHECK_46, feel free to take it for a spin, but just like everything else in ABAP there are most likely cases it does not cover.
<chorus>Hi Lars.</>
That is undoubtedly so, but to me, "tradition" is only ever the last argument to pull. "We've always done it that way" might also mean "we've been doing it wrong for the part 20 years".
Yup - I managed to baffle a (slightly over-confident, if I may say so) newcomer once by demonstrating a contraption that had an IMPORTING paramenter named EXPORTING and vice versa. However, IR_IMPORTING isn't that much better...
I still have your aOC project on the list of things to check out, but thanks for the heads-up!
an IMPORTING parameter named EXPORTING and vice versa. :-O
OK - that one made my day. ROFL.
Sounds like alcoholics anonymous meetings 😆
Well, if you're going to name check me and post something I think is utterly wrong 🙂 then of course you'll get a comment. And, despite the fact that I think you're wrong in principle (as well as specifically), I think you've written an interesting blog.
Main point:
In other languages that are used commercially, you will seldom see prefixes. What you will see are meaningful variable names. As the saying goes: follow the money. If prefixes were valuable (in terms of reducing maintenance and development costs), they'd be used in all programming languages, all the time. And they simply are not. https://msdn.microsoft.com/en-us/library/ms229045(v=vs.110).aspx
What's encouraged instead is meaningful variable names.
Subsidiary point:
I do not contend that all prefixes are bad. However, I do contend that g t s and r are not useful, harm readability and can encourage a certain type (hah!) of laziness.
Subjective point:
I find non-prefixed code easier to read and follow and therefore quicker to apprehend and quicker (and therefore cheaper) to fix. YMMV.
Specific points:
Instance attributes
g is not needed for an instance attribute. Use me-> instead. Me-> screams out loud to anyone who knows ABAP syntax that this is an attribute of this class. Just like this. in Java. To figure it out, I just need to know ABAP. To understand g I need to refer to some arbitrary prefix conventions in some document somewhere on the intranet. This is especially important when you've got a turnover of developers. The newbie could be in from another company who've decided that m is the correct prefix. He's got to read and remember your conventions. With me-> there's no such requirement. It's standard ABAP. A small saving - now multiply it by several thousand. (Which in fact it was this entire discussion is about - the overall effect of incremental improvements).
Static attributes
I do think marking static attributes (and methods) with some convention is useful. The problem with s is that it gets confused by so many developers with the structure convention! I'd like to use a simple _ - but there's really no obvious solution to this. Perhaps s is best.
Prefixing tables, structures, references...
Your example of description instead being gs_description does not represent a good argument for using prefixes. Abandonment of prefixes requires discipline in meaningful variable names. The attribute contains the text table entry. A good name therefore is text_table_entry. description, or even gs_description is misleading (and a little bit lazy?). It doesn't contain the description, it contains more than the description.
Your sflight example falls foul similarly. sflight TYPE TABLE OF sflight is a bad choice of variable name. It should be something like flights, or all_the_flight_data. Or Flights_information.
In both situations the issue/bug is caused by bad choice of name, not be lack of prefix. The preferred solution in my opinion is to use a good, meaningful name. Not regress to s or t. Table names are typically the plurals of their contents. Structured information is marked as so - in normal, readable English.
For me it's entirely obvious, without reference to a naming convention, that if I have a variable named widgets it contains a whole bunch of things each of which is a widget. If I have a variable named widget_information I know it's a bit more than just a single widget. Now, widget_information and widgets could be class instances, rather than a structure or a table, but that also is syntactically evident to any programmer.
I used to use r_company as a reference to a company (type ref to data). Now I use ref_to_company.
In a sense, constructing meaningful names in this way is replacing single character prefixes with (as in the previous example) longer prefixes. But this is fine - because the new prefix has a meaning in English, readily evident to programmers, without (until committed to memory) referring to the naming standards documentation.
Conclusion
I don't care much what conventions (or not) are used, so long as code is readable and maintainable. I think overuse of prefixes over complicates things and readability suffers. You've observed yourself that constructing a non-conflicting convention is very hard to do. So why even make the effort?
For companies who I rewritten their coding standards, I've drastically reduced the prefix requirement, replacing the majority with the simple injunction "Use meaningful names".
Some prefixes are helpful (e.g. for importing/exporting/changing) parameters. Others are not, and if they don't actively detract, they nonetheless add no value in comparison to meaningful names. And that's why I think you're wrong. 🙂
Matthew,
Thank you for your detailed comment. I think I understand your point better now, even thought I still don't agree in many aspects. Here's why...
As for the main point that if prefixes were useful, everyone would use them: I think you're oversimplifying things a bit. Programming environments (the programming language PLUS the entire ecosystem around it) differ radically from each other, as you are certainly aware of. You're referring to the .NET Framework naming conventions. .NET was released in 2000; at that time, ABAP had already been in the world for 17 years. The .NET and C# designers set out to create a "clean language" and "clean APIs" (whether they have succeeded is an entirely different discussion). For the ABAP programming language, that might have been similar (it certainly is nowadays, but if the legacy statements are representative, I'd say that wasn't always the case). For the enviroment, it certainly wasn't the case - one only needs to dig throught the layers beneath the shiny SALV classes to learn a lot about that. The growth of the ABAP runtime environment, as far as I can tell, has been a historically motivated, make-do growth rather than a beautifully architectured one. I don't want to defend it, it's just something we have to accept and cope with. If prefixes aren't useful in C# and Java, then partly because the designers of the language and the runtime environment had the power (and wisdom) to make it so. For ABAP, that was apparently not the case for an extended period of time (for the runtime environment it certainly wasn't).
[As for the "if it was useful, it'd be used everywhere all of the time" argument: Dead-man switches have been a very useful tool in avoiding accidents caused by train drivers, and cars are a land-based person-transport vehicle as well, so we should make dead-man switches in cars a legal requirement immediately, right? (Now brain-dead-man switches, that would be an improvement...)]
As for the "meaningful variable names" argument, I basically agree. However, I think that a) this is not enough (see reasons in my blog as well as below) and b) "meaningfullness" (is that a word?) is very subjective. To me, "zuzahlungsbefreiung_sgbv_p39_abs4" is meaningful; to you it probably won't be. Well, of course not - in your book, "meaningful" includes "in English", and many style guides I've seen actually make naming identifiers in English a requirement. That leads to a very awkward situation in my business area - there are tons of legal requirements with typical German names (Wiederkehrergesamtfallzusammenführungsstornogrund anyone?) that, being "brain-children" of the German regulatory system. have no "natural" equivalent in English. Maintaining a dictionary of these terms is possible, but very time-consuming and - given the lazyness of the average developer - not of much use anyway unless you employ someone to specifically check each and every identifier for "meaningfullness". If you did that, I'm pretty sure you'd lose a lot of experienced and valuable contributors that way. While I'm totally in favor of meaningful identifiers, I probably wouldn't particularly enjoy working in an environment where someone would be constantly harassing me to rename my variable from adm_diags to admission_diagnoses just because.
Side-note: Even without the inventiveness of the respective legal entities, ugly translation issues can and do happen. I have to deal with one frequently. IS-H and i.s.h.med contain a document management system which is based upon the 'DRAW DMS'. As you probably know, the 'DRAW documents' are categorized using a field named 'DOKAR', from 'Dokumentart', which has been translated to 'document type'. In IS-H and i.s.h.med, we need to further differetiate documents, so a 'Dokumenttyp' was added (technical name 'DTID'). That has been translated to 'document category'. It goes without saying that the potential to confuse 'document type' and 'Dokumenttyp' which sound/look very similar but are two entirely different properties is rather high.
Addressing the 'g_' vs. 'me->' convention: Again, I basically would love to agree, but there's a problem: If you omit 'me->', it still works. A developer can access and modify an instance attribute without the 'screaming out' bit and nothing happens. Pretty soon, the lazier members of the team (or off-shore contractor...) will stop using 'me->' altogether, while even the most dutiful developer will, given enought time, eventually simply forget the 'me->'. Now if this was a Java shop, one might simply make setting 'Unqualified access to instance field' to 'Error' in the Eclipse settings mandatory - problem solved. In ABAP, we don't have that flexibility (I wish we did!), but we have a Code Inspector check that can at least check for naming conventions. (And then start to argue about meaningful variable names in English with the Elbonian contractor...)
Meaningful for me includes German and French. Just sayin'... 🙂
In brief:
The link for .net was an example. Not the entirety. And I'm simplifying to make a general point. Your argument appears to be "much of ABAP is like this, so we need to stick with it". Horst Keller would disagree, I feel. Also, it's not much different from the argument you've already rejected that "it's tradition".
t__ s_ are not meaningful in any language. They have to be ascribed a meaning arbitrarily - although again an appeal to tradition - that all ABAPpers know these prefixes - could be made. Instead you could use table_of_widgets and widget_information. You could even say the prefix for internal table is table_of_ - that's still better than t_. In Java, I might well use list_of_widgets, for example.
Meaningful means(!) meaningful in context, and is a subjective judgement. It doesn't mean meaningful to everyone in all circumstances. Nor does it mean "meaningful to the off-shore support team that it's all been outsourced to". If a program is written for a German health insurance company, then I think it reasonable to expect any maintainer to have an understanding of some of the terminology, and program using some of those terms. If the company than offshores to a non-German speaking company, they've only got themselves to blame! In my experience, even the clearest English doesn't improve things much...
If you don't like me->, replace it with me_ . Best of both worlds, perhaps? And still better than g_ which is what - global? - so it's not even semantically correct.
Your argument about picking things up with Code Inspector fails, because automated standard enforcements don't really help with produce good programs. All is does is ensure that some arbitrary standards are adhered to that (as I've argued) actually add little value. It doesn't look at whether the programs are well written, well constructed, easy to maintain and support at 3am on a Sunday morning. I.e. you have to go beyond CSV, GxP requirements.
For that you need source code review (a competent conscientious experienced developer eyeballing the actual code). If you have that your lazy programmer will be rapidly identified and told to either shape up or get out. Even if your lazy programmer is forced to use prefixes by code scanning, you'll find that his laziness will manifest itself somewhere else that can't be so easily picked up on. Therefore you need source code review regardless.
I've implemented peer review of source code in three different companies, and everytime seem a real uplift in first time quality. Most programmers who program badly do so because they've never been taught otherwise. Source code review means that for the first time they can be shown the errors of their ways.
Hi all!
Wonderful VS discussion We're talking about if it's ok to drive car on the left or right of a road.
I think that if there's freedom then you have to choice and if you have to choice then you can do mistakes. Without errors you can't grow up, so it's better to be free than to be in a cage.
It's up to you to make errors in an exercise context or in a go live context, and that can be the difference between life or death.
Exercise helps in all matters. So to say something more I would only add that:
"Not only junior members need these tips but all people who doesn't care for someone else". I believe there's a great side of "Seniors" acting like they passed 100 lives on this earth . They should recover their will and start to think that life has always something to show and you must be foolish to think that there's nothing more to know.
This is a nice blog!
To be honest, I don't care if someone uses prefixes. Just so long as I'm not forced to.
I very nearly ended up on a project where version management was by comments in the code... fortunately the project manager in charge of that one moved on before I joined.
I usually hate to act like a teacher, but version management by comments in the code ... he must be a lover of self harm 😀 😀 or most probably he hates his workers.
Tons of uber alles consulting companies are well known "paper creators".
I guess he got that kind of imprinting/teaching 😛
Sure! I'm agree! And "fratelli d'italia" consulting companies too. As someone said: "
Watch ye therefore, for ye know not
when the master of the house cometh"
😀
With Uber Alles i mean the big internationl brutes (i've to name them? 😀 ), not just the German ones 😛
Thanks for this great discussion. I prefer the prefix version also. I agree with Volker that finding "meaningfull" names is hard and very subjective. Many times I replace my "meaningful" names with the names of the datatypes I want to address.
So
becomes
Okay this is a very simple example but you got the point. I use the forward navigation very excessive to find components which are suitable for my needs. With the variables named like the data type it becomes clear to every successor which data is contained in it.
Okay, sometimes there is a a need for holding different aspects of the same data type, then I suggesst to suffix the names with descriptive addons, e.g.:
So
DATA lt_all_flights TYPE TABLE OF sflight
becomes
DATA lt_sflight TYPE TABLE OF sflight
What's wrong with DATA all_flights TYPE TABLE OF sflight. The whole thrust of the prefix/not prefix argument is how much type information you need in the variable name. The "for" argument say "as much as possible". The "against" argument says "none at all so long as the name reflects what the variable represents".
Frankly, it seems that prefixing encourages reduced meaning in variable names. And that is a bad thing.
Matthew, you maybe right if the meaning is to the point. As Volker mentioned in his other reply (DRAW cs. ishmed document types) the situation becomes worse if there are many data types with similar information or description.
all_flight is to the point I have to agree but I see many times variables like documents. Okay, what type of documents may be in there? Most of the time you guess the content or refer to it using forward navigation.
If the variable was lt_draw everybody see the contents at a glance (no further investigation required). It is a TABLE of draw structure.
For me, a key aspect of programming is abstracting away from the technical detail. Therefore your programming that uses the draw information should only be concerned with the aspects of that. Within that part, I would suggest that: table_of_draw is more obvious than lt_draw.
LOOP AT table_of_draw INTO line_of_draw.
ENDLOOP.
All nice and clear, within the context of the DRAW table, no need for arbitrary and often inconsistent prefixes.
I wouldn't say it's "wrong", but it has the disadvantage that you can't tell whether you're dealing with a local variable or an attribute without explicitly looking it up.
No, it isn't, and I'm a little disppointed you keep putting it that way.
The "for" argument says "a little more doesn't hurt if it serves to prevent some nasty bugs". As I've tried to point out.
OK. The anti-argument is that is it encourages obscure variable names and doesn't really help improve the quality of programs and actively harms readability. So any benefit (which I contend is minimal if it exists at all) is entirely outweighed by the harm.
As far as signalling local, shadowing isn't flagged up as a major issue in other languages, so I find it very hard to believe that it is a major concern in abap. If shadowing is causing problems, then I'd suggest the real issue is careless programmers, possibly coupled with overuse of globals.
If a development is well structured, with good abstraction and separation of layers, you'll never be in the situation where shadowing occurs. You won't need to use local_table_of_all_flights because in your program design the idea of a global table of all flights won't make sense. I might we use some subset_of_flights
The nasty bugs you refer to, it seems to me, will only occur if the programming design is fundamentally poor..
I demand my prefixer safe-space on SCN 🙂
It's over there at L_SCN... Wait, why are you picking up that stick...?
... and still I don't understand, why in all these conventions there isn't a rule to prefix a structure or a table in a structure, if it so important to prefix at all.
DATA:
BEGIN OF ls_struct,
col1 TYPE struct_type
col2 TYPE TABLE OF struct_type,
END OF ls_struct.
is OK?
Why not
DATA:
BEGIN OF ls_struct,
s_col1 TYPE struct_type,
t_col2 TYPE TABLE OF struct_type,
END OF ls_struct.
Cheers!
Horst
From a shadowing standpoint: Because you can't shadow a global col1 with ls_struct-col1, so it's of no use there. But you've got a consistency point there, no doubt.
As Volker said, it is of no use here. But I must admit that I structure my own datatypes like
Or, to be more precise I include the project (aka package name e.g. )
I like this analogy.
Actually, an object is an extended version of a structure, allowing for method components, not only data components. It is not consistent to require a prefix for an object component but no prefix for this same component if it belongs to a structure (which is a method-free object). The component is the same, independent of whether it is embedded in an entity with or without methods.
Also, I find the expression
customer->total_revenue
way better readable than something like (the arbitrary details depend on the company's guideline):
lo_customer->gv_total_revenue
The most important thing are the names of the variables. I want to see - in the clearest way possible - that I deal with a customer's revenue. The rest is noise!
If the methods are small, there is no problem with the context. And here comes the culture point: The average method in ABAP is not small, it is more likely to have 500 than 5 lines. I don't have the time to rewrite every code which I am supposed to correct or modify. So in the real ABAP world, prefixes do make sense, and this is the only reason why I accept them.
But I'm not happy with them.
Just looking at the class I'm about to be working on. The longest method has 40 lines of ABAP. And that's because it's using a function module with a large signature!
Perhaps the corollary could be drawn - overuse of prefixes indicates poor modularisation. 😉
Pragmatic 😳
I guess at some point one has to close his eyes & take the plunge (of not using prefixes). I was happily using
until i feel in love 😘 with
Hi Volker,
Naming conventions always give a nice discussion 🙂
A little tip for the ABAP trapdoor:
Instead of:
LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).
DELETE TABLE sflight FROM <sflight>.
ENDLOOP.
Use:
LOOP AT sflight ASSIGNING FIELD-SYMBOL(<sflight>).
DELETE sflight USING KEY loop_key.
ENDLOOP.
Regards,
Robin Vleeschhouwer
Interesting blog here: Making Wrong Code Look Wrong - Joel on Software which could be adapted to argue that s and t are useful prefixes, but i, e, l etc. would not be.
The thrust of the argument is that Hungarian Notation is useful when it allows you to spot errors immediately, but otherwise to be avoided.
So
LOOP AT t_flights INTO t_something_else
Is instantly identifiable as wrong. But for all others, you have to (manually or otherwise) check the code. I.e. if I use l_blah = g_fish. And blah is global and fish is in fact local - you can only discover this by examining the code, and therefore such prefixes add no value.
???
DATA:
lt_itab1 TYPE TABLE OF i,
lt_itab2 LIKE TABLE OF lt_itab1.
LOOP AT lt_itab2 INTO lt_itab1.
...
ENDLOOP.
OK, clearly identifiable in the vast majority of cases as wrong. However, at first, I thought this is just a pathological example. But on reflection, it appears to be an extremely good example of the failure of t_ and s_ And it isn't pathological; I've used things like this myself.
Wait a moment - t_ is to be used for types (and that's not my invention), so using t_ for DATA is wrong in the first place, right?
Oh sorry, I forgot the l. It must be lt_itab1, lt_itab2, to follow the convention, dang!
But even then, you're labeling something as a table that isn't one. That's just as bad as having a variable named 'list_of_numbers' that just contains a single number (albeit a few characters saved... *duck&run*).
Both are tables (now ...)
If something is mislabeled or misnamed, it is wrong. It doesn't matter if the prefix is applied incorrectly or the meaningful name is misleading, it needs correcting even if it is syntactically valid.
If I see
LOOP AT something ...
or
something[ ... ]
in an ABAP program, it is absolutely clear to me, that something is an internal table.
If I see
... something-somewhat ...
in an ABAP program, it is absolutely clear to me, that something is a structure.
What the heck do I need those t_ or s_ for?
Attention, I'm getting polemic now:
Those t_ and s_ are good for programs where you still write CALL METHOD meth instead of meth( ) or use COMPUTE in front of calculations or stay with READ TABLE t_something instead of using something[ ... ] (and keep away from all that "modern" stuff at all).
Cheers!
Horst
As long as you keep in mind (as I'm certain you do) that a) not all of us have the luxury of using the latest releases all the time and b) the majority of developers couldn't care less about the finer aspects we're discussing here, feel free to get polemic 🙂
I wholeheartedly agree with Matthew on using long descriptive variables and I also agree with Volker that using (in my case limited) prefixes speeds up development when you're accustomed to using CTRL+SPACE.
I used to think prefixes were a good idea. I used to think that declaring all the data at the top of the modularisation unit was a good idea.
Then, as an experiment, I tried ditching type prefixes, and declaring data just before it is used, and I've never looked backed. The point is that all the worries and scenarios concerning non-use of typing prefixes disappear - it turns out there's very rarely any kind of problem relating to them at all. Some will say "well, if it doesn't make a difference, why not keep them". The answer is - why put something in that is redundant.
I use CTRL+SPACE all the time and have for ages. I didn't find the switch to non-type-prefixed code slowed me down at all. Why should it? The majority of coding time should be spent thinking, not typing! 😀
I can partially agree with Matthew (I use prefix without thinking too much about them but I did the same experiment he did with the same result).
What I do not agree so much is keeping declaring stuff in the middle of the code (except if you are using inline declaration, but as Volker stated before, sometimes you cannot put your hand on lastest resleases 🙂 ): it's a damn mess and if you are smart and good and never duplicate a memory area (call it variable, structure, internal table, mommy's pie), the next guy who puts his hands on it could not be so smart and starts to duplicate things usesless.
Having declaration at start of the module you are implementing (FORM, Function, Method) helps the next guy to know what he already got at disposal.
This even if we follow the empiric rule "A module should stay in a screen: if you have to press page down to reach the end, modularize better"
I agree again with Simone, however, in a lot of cases prefixes are specified in the companies coding standards so ditching them is not an option.
Rich
The trick there is to make sure you're the person who's responsible for the coding standards. 😉
Yeah... Okay...<Sigh>.
The first time you decide that a bit of code would be better off in a separate method, you'll suddenly find out why variables declared in the nearby context is better. 🙂 Note, I say nearby context. I don't insist at all that all variables are declared on the line just before they're used.
Nearby declaration keeps code that belongs contextually together in the same place. No scrolling. This is widely regarded in programming as a "good thing".
If you have properly modularised and used whitespace effectively, it doesn't have to be a damn mess. And eventually, you will be on a 7.4+ system.
Sorry but I stated clearly (or at least i thought it 😛 !) that inline declaration are something out of scope in this discussion (at least from my point of view).
I easily use inline declaration and still i prefer, when i cannot use it, having a more clean code with top declaration.
Call me old grumpy developer! 😀
You did. And I edited my post to address that once I'd realised. 🙂
Darn! And with my answer i earn my grumpy's badge! 😛
In this case, i can almost agree with you 🙂
I still prefer (old habits that do not arms anyone) having the top declaration but using the empiric rule "all in a screen" it doesn't matter so much anymore 🙂
Hi Grumpy 😏
I tried to reply to your latest post about monsters but even though I've been notified about it I can't find it. ..... 😕
But what I wanted to say is don't you just hate constants defined like:
Constants: c_s Type c Value 'S'.
Why not:
c_Debit Type Shkzg Value 'S'
Then when you read it in the code it makes sense rather than wondering what 'S' means....
Rich
Scroll down! 😀
Anyway, it depends, imho.
If I need to check an 'S' with different meanings, a generic declaration C_S seems to be more suitable than C_DEBIT.
In faith,
your
Yes, that sounds right.
In one program "S" might mean "success message" and in another place "shared lock" and in another place "debit" and in another place "synchronous" and in HR it sometimes means "run type for pension calculation"
So in my program that does pension calculations, and sometimes debits the pension, and often locks the record, and if not sends out success message I just put "C_S" as opposed to "= 'S'" all over the place and then suddenly everyone understands.
Even better when SAP decides "run type for pension calculation" is now "T" instead of "S" that cannot possibly have an adverse effect.
Hey Grumps.... 😆
Ok, but it depends on the context that it is used in, and if there were multiple 'S's.. then there should be multiple constants. Makes the code more readable!
And completly mess, full of useless data/constants.
Why do you want to complicate your life? 🙂
As I said - makes the code more readable. You know without having to lookup what the value means what you are selecting/comparing/printing whatever.
Rich
I'll take your "SHKZG" constant and raise you a "JEST" constant.
It turned out that when a piece of equipment in PM was inactive then the status of "IE0076" in JEST meant it was inactive.
So one of our consultants wrote:-
CONSTANTS: c_ie0076 TYPE jest-stat VALUE 'IE0076'.
I also like statements like
CONSTANTS: c_value_five TYPE I VALUE '6'.
Actually that one is particularly evil trap because these internal status numbers aren't constant. A status ABCD may have a number E0076 in one status profile and E0054 in another.
Let's see...
CONSTANTS c_ascii_s TYPE c VALUE 'S'. " because ASCII might be changed some day
CONSTANTS c_my_s TYPE c VALUE c_ascii_s. " so if we change to another encoding, we only have to change it once
CONSTANTS c_our_s TYPE c VALUE c_my_s. " because there is no 'my' in 'team'
CONSTANTS c_debit TYPE c VALUE c_our_s. " that's just obvious
CONSTANTS c_money_minus_minus TYPE c VALUE c_debit. " because 'debit' is a term not every developer understands
Yep, great thing we've got these constants after all...
I kid you not, I have seen all single digits constantized:
CONSTANTS: c_zero value 0,
c_one value 1,
...
Actually that's one of my pet peeves: Having to jump 200 lines back and forth between declaration and code to figure out what type of structure ls_po and ls_doc actually is.
If you got 200 rows of code, you got an bigger prolem in your (generic "you"! 😉 ) code's structure and modularization.
I usally have a split pane open with the start of the module/method/whatever in the top pane. So jumping around isn't an issue for me.
That is one of the places where the ADT / ABAP in Eclipse tools are really handy - I always have the element info view lurking at the bottom of the screen so that I can quickly lookup the element type info.
Good point, Eclipse does go one step further in making prefixes unnecessary.
I suspect this saga will continue until Matthew Billingham joins The Order of Prefixers or uses his powers to ban this subject from ABAP space forever. 🙂
Just to make it clear: I'm aiming for neither. Just trying to add a little grey-scaled background to the black-and-white that is so prevalent...
Ohhh, that sounds almost as if you are in the prefix camp. That be fightin' talk! 😉
But seriously, there is good reason for both: If you're working with last decade's code it probably benefits from prefixes. If you write new, or just have the opportunity to rewrite with modern capabilities and principles, it doesn't. Simples.
Personally, I don't feel strongly either way, to be honest. Prefixes are fine as long as they are consistent. No prefixes is fine as long as the names are descriptive. Lack of consistency and non-descriptive names are the real issues here IMHO.
P.S. I do hate wa_ prefix though. It's a structure, people! 🙂
The former ain't gonna happen. Once you leave you never go back. (That's why I encourage people to try it).
The latter won't happen. Though I'd probably reject another blog on the subject - either for or against! I doubt there's much more to be said.
Hi Volker (et al),
An important topic that will never get resolved except by the champion at individual consultancies/companies...
That said, the one thing I think everyone should agree to is to name the variable well, and stop shortening for the sake of shortening. e.g. LV_CUS and CUS both don't really help tell you what the variable is without a lot of context; as opposed to customer_name (as an example).
Cheers,
Matt
ps. BTW - In ABAP, with it being a fairly junior developer playing field for the most part, I think a level of naming is required for the foreseeable future, but I'd recommend dropping "v" for variable as this should be the default and will save you a character.
edit: Originally had 'drop the "l"', but realised I meant drop the v so that you only differentiate objects, tables and structures...
Hi Volker,
Needless to say you picked a 'hot topic' to blog on.
Have a look at these comments:
Comment 1
Comment 2
Thanks,
Juwin
This discussion reminds me: If no prefixes is the SAP-recommended way, why does the relatively recent Web Dynpro builder generate ghastly lv_'s?
I figured out how to hack the table control wizard a few years ago - I must figure out how to hack the Web Dynpro Builder to remove these ghastlies... when I have some time.
OK, got it now.Enhance Cl_Wdy_Rg_Fragment_Tool
e.g. Add an implicit enhancement to method GEN_CONTEXT_NAVIGATION and re-work the string table "result".
As I said, I am going through the code in my book, losing all the prefixes.
That forces you to have meaningful names, so you can tell what is a table, structure, or what have you, which is great.
I just found a variable, which I had named, in my infinite wisdom, as follows:-
DATA: lt_monster_item_table TYPE zttyp_monsters.
Can anyone see what is wrong with that? I had a good giggle.
Apropos of nothing, I also find some German names meaningful ( e.g. STD as an abbreviation for "hour" is understandable) , as I work for a German company, lived in Germany, and speak German after a fashion. In fact sometimes I think if standard SAP code had longer German names for variables instead of bizarre abbreviations it would make it easier to follow.
I also think that standard SAP code has moved, in recent years, from every programmer doing something different, some with no prefixes, some with prefixes, no two people using the same convention for prefixes, to everybody using prefixes with pretty much the same convention. Consistency is great, though ironic SAP decided to move to using prefixes when I decided to move away from this practise.
Maybe they knew I has stopped using prefixes, so they then decided to start using them, just so they could continue doing the opposite of what I do.
DATA: lt_monster_items_table TYPE zttyp_monsters.
A little letter missing 😀
Now, could i have the doll i won? 😛
That could be a deep table of monsters, with each line containing a monster and a table of items the monster is carrying. 😛
Or we could also be talking about lt_monsters_item_table
Then again "lt_" makes the "_table" and either plural "s" redundant.
There's also a discrepancy that the data type refers to monsters and not items. So we're writing the equivalent of:
data: lt_ekpo type standard table of ekko.
I had an importing variable, that contained the name of a rule. I think the constant use of i_rule reinforced my megalomania... 😛
Also, in WEB DYNPRO methods, have you noticed how often the importing/exporting parameters od not have prefixes, but the (generated) local variables do?
That's the wrong way round is it not?
You have heard the phrase "cannot see the wood for the trees". The Web Dynpro things I had got used to, it is only looking back and taking another look you realise how silly it all is.
Here is a question - do some VAR declarations in JavaScript code in UI5 applications seem to have prefixes, or is that just an illusion?
I omitted prefixes a while ago and my code became a lot more readable instantly.
I usually follow the official guidelines and only prefix importing/exporting/etc. parameters on method signatures and global variables with g_* (but globals should be extremely rare in newly written ABAP code anyway).
I think for the major contributor's to this blog it wouldn't matter a jot whether they used prefixes or not. They both care about clarity and simplicity and their code would be easy to follow. However, I think for the rest of us, in general, using prefixes is usually easier to follow and introduces less confusion. I often struggle to provide meaningful names and I don't think I am Robinson Crusoe on this. Meaningful is also quite subjective and therefore vulnerable to misinterpretation. However, as a contractor I am always happy to follow my current site's ruling on this!
Made my day 😀