Nomen est Omen – ABAP Naming Conventions
Introduction
My comment about the importance of ABAP naming conventions to Thorsten Franz’ blog Great Programmers will their Code to the new Guy triggered an interesting discussion about naming conventions for ABAP. The opinions range from “…is important” to “…We do not advise you on naming conventions, do whatever you want”.
The latter statement sounds like a capitulation. This resignation might be due to the following questions:
- Are there useful naming conventions for ABAP? Apparently not even SAP has them.
- Do naming conventions really improve ABAP coding and how?
- How can we check the compliance of ABAP program objects with the naming conventions?
ABAP Naming Conventions: “Yes, we exist”
I started my SAP career more than 10 years ago at Cirrus Consulting. The very first thing I got there was a comprehensive documentation about ABAP naming and programming conventions which they had created for one of their biggest customers. And at the Zürcher Kantonalbank they had such a document, too.
Admittedly there were deviations from these conventions in particular because many external developers worked at these customers and the Code Inspector (SCI) was not yet available at that time. Nevertheless these conventions facilitated the readability of the coding and the handing over (for maintenance) to other developers. And if you look carefully around you will realize that even SAP (or at least a subset of its developers) uses naming conventions.
Now let us imagine a “…do whatever you want” customer where a developer creates a report (containing a constant for the speed of light) which in the subsequent years has been maintained by three other developers. Three of them use their own naming conventions and the forth one uses none at all so we may end up with the following representations of a single constant:
- GC_LIGHTSPEED or LC_LIGHTSPEED
- CO_LIGHTSPEED
- C_LIGHTSPEED
The forth developer may replace all previous representations with his own SPEED_OF_LIGHT without any prefix because everybody “knows” that this is a (pyhsical) constant. This medley of naming conventions will definitely confuse every developer. And this is just a simple example considered with the mixing up the naming of global and local variables.
In the following section I will present my own naming conventions which are a “best-of-breed” blend of SAP naming conventions and those of my previous employers.
Call a Spade a Spade
Naming conventions must be concise, short and distinct. Any ambiguity is a burden for maintenance in the future. Using three categories of criteria it is possible to unambigously name virtually all variables and most signature parameters:
- Visibility: Global / Local / Class Context
- Type: Field / Structure / Table Type / Reference / Constants
- Structural Context: FORM routines / Function Modules / Methods
There are two general naming conventions:
- Variables and Class Attributes: <Visibility>_<Type>_<Description>
- Signature Parameters: <Structural Context>_<Type>_<Description>
Visibility & Type
We have three kinds of visibility: Global, Local and Class Context (which includes Interfaces as well) and seven different types (see below).
Visibility | Prefix |
Type | Prefix |
Example | Coding |
Global | G | Field | D | GD_MATNR | DATA: gd_matnr TYPE matnr. |
Structure | S | GS_KNB1 | DATA: gs_knb1 TYPE knb1. | ||
Table Type | T | GT_VBAK | DATA: gt_vbak TYPE TABLE OF vbak. | ||
Class Interface |
O |
GO_GRID GO_MSGLIST |
DATA: go_grid TYPE REF TO cl_gui_alv_grid. DATA: go_msglist TYPE REF TO if_reca_message_list. |
||
Data Object | DO | GDO_DATA | DATA: gdo_data TYPE REF TO data. | ||
Constant | C | GC_LIGHTSPEED | CONSTANTS: gc_lightspeed TYPE i VALUE ‘300000’. | ||
Local | L | Field | D | LD_MATNR | DATA: ld_matnr TYPE matnr. |
Structure | S | LS_KNB1 | DATA: ls_knb1 TYPE knb1. | ||
Table Type | T | LT_VBAK | DATA: lt_vbak TYPE TABLE OF vbak. | ||
Class Interface |
O |
LO_GRID LO_MSGLIST |
DATA: lo_grid TYPE REF TO cl_gui_alv_grid. DATA: lo_msglist TYPE REF TO if_reca_message_list. |
||
Data Object | DO | LDO_DATA | DATA: ldo_data TYPE REF TO data. | ||
Constant | C | LC_LIGHTSPEED | CONSTANTS: lc_lightspeed TYPE i VALUE ‘300000’. | ||
Class Context | M | Field | D | MD_MATNR | DATA: md_matnr TYPE matnr. |
Structure | S | MS_KNB1 | DATA: ms_knb1 TYPE knb1. | ||
Table Type | T | MT_VBAK | DATA: mt_vbak TYPE TABLE OF vbak. | ||
Class Interface |
O |
MO_GRID MO_MSGLIST |
DATA: mo_grid TYPE REF TO cl_gui_alv_grid. DATA: mo_msglist TYPE REF TO if_reca_message_list. |
||
Data Object | DO | MDO_DATA | DATA: mdo_data TYPE REF TO data. | ||
Constant | C | MC_LIGHTSPEED | CONSTANTS: mc_lightspeed TYPE i VALUE ‘300000’. |
The vast majority of variables within program objects are either global or local. And in the future there will be a remarkably shift towards class attributes (ABAP-OO). Thus, assigning a unique prefix to each group makes their visibility unambigous for every developer.
Class attributes (instance and static) are special because they are global within the class/instance whereas they appear local from outside the class/instance. Without referring to a class(name) or instance these attributes are “hidden” (i.e. local).
Question: Does the type prefix offer any benefit?
In ABAP forum posts you may find the following definitions for ALV grid instances:
- GRID: global (?), local (?), class context (?); class reference (?)
- G_ALV_GRID: global (!?), local (?), class context (?); class reference (!?)
- GO_GRID: global class reference OUTSIDE any class context (my naming convention)
Answer: Yes, because we meet the developer’s expectation and anticipation.
You may argue: What a big fuss about such a little subtlety. My answer to this is: Every SAP developer who comes across a GO_GRID variable in any of my programs knows in advance(!) the meaning and scope of it.
Structural Context (1): FORM routine Signature
The SAP system does not care about which kind of formal parameters (USING or CHANGING) are used in FORM routine signatures. Both kinds of formal parameters can be changed within the routine and the modified contents transferred back to the calling program. This is ambiguity at its worst.
In order to make the signature of a FORM routine clear as crystal we define every Input = USING parameter and every Output = CHANGING parameter. Within the FORM routine all USING parameters should be regarded as “constants” meaning that they are not changed nor is any change transferred back to the calling program.
Parameter | Prefix |
Type | Prefix | Example |
USING | U | Field | D | UD_MATNR |
Structure | S | US_KNB1 | ||
Table Type | T | UT_VBAK | ||
Class Interface |
O |
UO_GRID UO_MSGLIST |
||
Data Object | DO | UDO_DATA | ||
CHANGING | C | Field | D | CD_MATNR |
Structure | S | CS_KNB1 | ||
Table Type | T | CT_VBAK | ||
Class Interface |
O |
CO_GRID CO_MSGLIST |
||
Data Object | DO | CDO_DATA |
Again, by defining Input = USING (prefix ‘U’) and Output = CHANGING (prefix ‘C’) we meet the developer’s expectation and alleviate understanding of the FORM routine.
Structural Context (2): Function Module Signature
The same logic applies to function modules parameters. In addition, we can facilitate the understanding of TABLES parameters (Yes, I know they are obsolete yet some still like to use ’em) by the semantics of their Input/Output behaviour:
- IT_ITAB = Input only
- ET_ITAB = Output only
- XT_ITAB = Input & Output
Parameter | Prefix |
Type | Prefix | Example |
IMPORTING | I | Field | D | ID_MATNR |
Structure | S | IS_KNB1 | ||
Table Type | T | IT_VBAK | ||
Class Interface |
O |
IO_GRID IO_MSGLIST |
||
Data Object | DO | IDO_DATA | ||
EXPORTING | E | Field | D | ED_MATNR |
Structure | S | ES_KNB1 | ||
Table Type | T | ET_VBAK | ||
Class Interface |
O |
EO_GRID EO_MSGLIST |
||
Data Object | DO | EDO_DATA | ||
CHANGING | C | Field | D | CD_MATNR |
Structure | S | CS_KNB1 | ||
Table Type | T | CT_VBAK | ||
Class Interface |
O |
CO_GRID CO_MSGLIST |
||
Data Object | DO | CDO_DATA | ||
TABLES | “Importing” | IT | IT_VBAK | |
“Exporting” | ET | ET_VBAK | ||
“Changing” | XT | XT_VBAK |
Of course there is no technical difference whatsoever between “Importing”, “Exporting” and “Changing” TABLES parameters. Yet the different naming gives the developer already an idea about the function of this module without looking into the coding. Or in other words: Try to “express” the function of the module already in its signature.
Structural Context (3a): Method Signature
The logic explained above is just applied to method parameters as well and extended to the additional RETURNING parameters of methods.
Parameter | Prefix |
Type | Prefix | Example |
IMPORTING | I | Field | D | ID_MATNR |
Structure | S | IS_KNB1 | ||
Table Type | T | IT_VBAK | ||
Class Interface |
O |
IO_GRID IO_MSGLIST |
||
Data Object | DO | IDO_DATA | ||
EXPORTING | E | Field | D | ED_MATNR |
Structure | S | ES_KNB1 | ||
Table Type | T | ET_VBAK | ||
Class Interface |
O |
EO_GRID EO_MSGLIST |
||
Data Object | DO | EDO_DATA | ||
CHANGING | C | Field | D | CD_MATNR |
Structure | S | CS_KNB1 | ||
Table Type | T | CT_VBAK | ||
Class Interface |
O |
CO_GRID CO_MSGLIST |
||
Data Object | DO | CDO_DATA | ||
RETURNING | R | Field | D | RD_MATNR |
Structure | S | RS_KNB1 | ||
Table Type | T | RT_VBAK | ||
Class Interface |
O |
RO_GRID RO_MSGLIST |
||
Data Object | DO | RDO_DATA |
Structural Context (3b): Static vs. Instance Attributes
Static attributes are special because they exist only once for all instances of this class. Modifying a static attribute within a given instance makes this change visible to all other instances. Both types of attributes have the prefix ‘M’ (class context) in my naming convention. In order to distinguish between static and instance attributes I apply the following convention:
- Instance Attribute: with self-reference me-> (e.g. me->md_key)
- Static Attribute: without self-reference (.e.g. ms_row)
You can find an example of this naming convention in the coding of INCLUDE ZRSWBOSDR_C01 in my blog Multi-Purpose ALV Programming.
Another unambigous convention is to drop the self-reference prefix and use the full qualified name for static attributes:
- Instance Attribute: md_key (with or with self-reference prefix)
- Static Attribute: lcl_eventhandler=>ms_row
Field-Symbols
We can apply the same naming conventions even to field-symbols which makes them much more readable and understandable for every developer. This is particularly important because the contents of field-symbols cannot be analyzed statically but is only determined at runtime.
Visibility | Prefix |
Type | Prefix |
Example |
Global | G | Field | D | <GD_MATNR> |
Structure | S | <GS_KNB1> | ||
Table Type | T | <GT_VBAK> | ||
Class Interface |
O |
<GO_GRID> <GO_MSGLIST> |
||
Data Object | DO | <GDO_DATA> | ||
Local | L | Field | D | <LD_MATNR> |
Structure | S | <LS_KNB1> | ||
Table Type | T | <LT_VBAK> | ||
Class Interface |
O |
<LO_GRID> <LO_MSGLIST> |
||
Data Object | DO | <LDO_DATA> |
SAP and Lego
Why has Lego become one of the world’s most famous toys? Part of the answer can be found here:
“Lego pieces of all varieties are a part of a universal system. \ Despite variation in the design and purpose of individual pieces over \ the years, each remains compatible in some way with existing pieces. \ Lego bricks from 1958 still interlock with those made in 2009, and Lego \ sets for young children are compatible with those made for teenagers.
\ Bricks, beams, axles, mini figures, and all other parts in the Lego \ system are manufactured to an exacting degree of precision. When \ snapped together, pieces must have just the right amount of strength \ and flexibility mixed together to stick together. They must stay \ together until pulled apart. They cannot be too easy to pull apart, or \ the resulting constructions would be unstable; they also cannot be too \ difficult to pull apart, since the disassembly of one creation in order \ to build another is part of the Lego appeal. In order for pieces to \ have just the right “clutch power”, Lego elements are manufactured \ within a tolerance of 2 µm.”
QUESTION: “Have you ever seen a child which sits in front of a pile of Lego bricks claiming it can’t build anything because all bricks have the same size???”
For me SAP is just an incredibly huge pile of Lego bricks (for grown-ups). Consistent naming conventions are an indispensable standard which enables us to manufacture long-lasting developments that are easy to understand and maintain (pull apart and reassemble).
Code Inspector: Check Compliance with your Naming Conventions
The Code Inspector (transaction SCI) provides you with all means to check compliance with your naming conventions. Within the check variant you an explicit check Programming Conventions.
Looking at the check Naming Conventions a popup appears where you can define your conventions for data variables and signatures (FORM routine, function module, classes).
Since I have not yet mentioned macros (DEFINE) yet here is my convention:
- MAC_<description>: e.g. mac_suppress_toolbar_btn
Another set of frequently used global variables are (select-)parameters and select-options:
SELECT-OPTIONS:
S_MATNR FOR mara-matnr.
PARAMETERS:
P_MATKL TYPE matkl.
Looking at the check Extended Naming Conventions for Programs you will find my 7 types (Field, Structure, Table Type, Class, Interface, Data Object, Constant) grouped into 5 prefixes:
- Elementary Type includes Field and Constant
- Object Reference includes Class and Interface
The prefixes shown above are the default values when opening the check with which I do not agree. For example, the prefix “R” indicates a global range according to my conventions:
DATA: rt_matnr TYPE RANGE OF matnr.
Summary
It is possible to define useful naming conventions for ABAP. Naming conventions significantly help in understanding a program and navigating around it. Both the new and the senior guy will benefit in particular when it comes to maintenance because they can focus their analysis on the program logic and not the “logic” of the previous developer.
Conclusions
Naming conventions are not impositions for creative developers but, on the contrary, side rails for long-lasting development.
Addendum
I no longer think it makes sense to explicitly distinguish between classes and interfaces because at the end of the day you always work with an interface implementing class (even if the static type is that of an interface). Therefore, the two separate rows for “Class” and “Interface” have been merged.
Further Readings
Cheers
Thomas
Nice to hear from you again. I take your 80% match as strong evidence that concise naming conventions exist. And it disproves all those claiming that there aren't any useful conventions nor using any of them. Congratulations if you are working for a customer who is aware of this important aspect of ABAP development.
Best Regards
Uwe
Nice work.
We definitely need unique naming convention for each type of data declaration and more importantly, it must be followed.
Surprisingly, my naming conventions are almost matching with what you have suggested.
Regards,
Naimesh Patel
Whenever I see a posting from you I check it because I can learn from it almost every time. Looking at your coding style (and that of Marcin Pciak as well) it is like watching my "mirror image". And that's perfect because it implies interchangeability between developers (= aim described in Thorsten Franz' blog).
Best Regards
Uwe
another great post. I have been using your naming conventions for some time. As I am a particularly unoriginal person I can only assume we have discussed these before somewhere. 🙂
Do you know if there is a way to get the compiler to warn you when you break your defined naming conventions?
Cheers
Graham Robbo
Looking through the comments to my blog you see that I just expressed what is obvious for good ABAP consultants.
Lacking time (due to the ever-growing demand of our Lindt companies for EDI implementations) I cannot answer your question (yet). But if I take up the idea by Paul Hardy (see above) then we will for sure find a way to enforce compliance with naming conventions with the SAP systems.
Best Regards
Uwe
This sound like a feature the SCI ("SAP" Code Inspector) transaction could manage. It's been a few years since I looked at the extensibility of that audit logic, but that would be the place for code standardization rules.
Jim
As a consultant, I have often run into a dilemma when I walk into a new project that has slightly different naming conventions than the one I follow. Is it better to introduce a more elegant naming convention, or do you aim for consistency and stick to whatever has been followed in the past? Once you have G_T* and GT_* both in your system, you are already in a mess.
Also, the naming conventions introduced in the pre-OO ABAP era do not always extend nicely to OO world.
Now if only we could have the liberty (and time and money and...) to rewrite old code 🙂
I am glad that you feel like me that there is a difference between G_T* and GT_*: both are distinct yet only the latter is concise and short as well.
As consultants we should convince the customers that software quality is much more than just "...It works.". Open the eyes of your customers for the important aspects "behind the curtain" and explain to them how they will benefit in the long-term (i.e. maintenance) if they invest a bit more time and money at the beginning.
Regards
Uwe
As much as you don't agree, and think you have a better way, just use the existing corporate policy.
Cavets
1. If you are making significant additions (maybe changes) ... Nah, not even here...
2. If you are willing, on your own dime, to re-engineer all of their code, document a standard, and then sell and train their developers on the new standard. Then yes, go ahead and change it.
Gosh that Mike Nichols guy must be old!
I must be really old as well...
I cannot fault any of your recommendations. At my company we are already quite close to what you suggest - I have seen people using GR for a global object as opposed to GO on the grounds that is a "reference variable" and just R for a global range, but after thinking about it I prefer your suggestion.
It would be great to get some sort of unofficial (or even offical) endorsement from someone at SAP as to your proposed naming standards. Maybe you could have some sort of on-line petition where various developers sign up to promise to try and start using your suggestion naming conventions. If you got enough developers agreeing on something it could put pressure on SAP to finally declare their position on this matter.
Cheersy Cheers
Paul
Thank you for your affirmative remarks.
My proposed naming conventions are by no means "rocket science" but nothing else than plain commonsense. Yet the coding I have seen in the past and the present proves that this sense is not so common...
I never thought about the possibility to put these naming conventions into the rank of a "SAP approved global standard". However, thinking about the implications I should pick up your idea.
Imagine we would have a worldwide standard for ABAP naming conventions:
- No customer would ever again struggle with developers using odd conventions because there is a single standard available (which can be checked and enforced by the Code Inspector)
- Wherever you go and work as an ABAP consultant you would have a head start when it comes to the maintenance of existing programs (= reduced costs for customers!!)
Regards
Uwe
I am now using your conventions on the grounds that I now use the same naming conventions as at least one other ABAP programmer on the planet, which is most likely one more than before. Just this is akin to a miracle - two ABAP programmers using the same naming convention instead of the status quo of tens of thousands of ABAP programmers, every one using different conventions.
I still advocate some sort of online petition, where we get SDN members who are ABAP programmers signing up saying they will use these conventions, until the time we have a global standard.
Cheersy Cheers
Paul
In every project that I've been work on, there's always naming standard defined usually with minor alteration between each of them. Most of them looks similar with your proposed naming convention. = space." in a large program, I will need to go back to data definition section to determine whether the statement is proper or not. I think I will revised my company naming convention for field symbols to adopt your approach. Thanks for the revelation Uwe.
I think you see my point: Field symbols are already disclosed by the brackets so the "FS_" does not add any useful information anymore.
Adding the type (field, structure, table type, etc.) may become particularly helpful if you need to debug in an Unicode environment where we are (fortunately) no longer allowed to use many "quick&dirty" statements (=> catchword "Unicode Fragment View").
Best Regards
Uwe
I totally agree. I really hate it when I see <fs...>. In a Class context, all field-symbols are necessarily local, but I still use <l_...>, even though it is redundant.
Sorry, I am guilty of using <lfs and <gfs respectively. I shall an endeavour to better myself and forgo the the prefix! Please forgive my sins. <br/><br/><br/>P.S. Great Blog Uwe! <br/><br/>Cheers,<br/>Neil.
First fully great post and I definitely agree that naming conventions make code more readable and it is worth to adopt them.
Still I'd like to challenge this "prefix everything" approach which seems to be kind of popular in ABAP world. Of course the upside of prefixing everything is that you immediately know what kind of variable that is and where it comes from. But there is huge downside also - when you have first glimpse at code all variables seem to be the same - all of those LC_* LD_* really don't look that good and are actually somewhat confusing in my opinion.
I would actually imply that there is kind of better way to make code more readable than "prefix everything" approach and that would be properly structuring the code. The thing is that if your code is well split into forms, functions, classes, methods and each separate unit contains reasonable amount of code (ideally less than 50 lines) there are no big problems to quickly figure out variable scope and meaning anyhow.
Of course, if follow old school ABAP approach and write some code where single logical unit (form, function, method) contains like 1000 lines of code, this "prefix everything" comes in handy. But do you really need it for normally structured code?
That being said, I'm not against prefixing in general - I still agree that you can/should prefix constants and global variables. But I would strongly oppose idea of prefixing each and every local variable.
But if it's there in the prefix, then you don't even have to figure it out. It's totally unambiguous. And ambiguity leads to costly confusion. While prefixing might not look so pretty, and steps away from natural language, I can't see how it is confusing, nor can I see the huge downside.
this. I totally agree with Reinis.
no other language needs these bulky prefixes to produce perfectly readable & understandable sourcecode.
Reinis very well sums it up with "Of course, if follow old school ABAP approach and write some code where single logical unit (form, function, method) contains like 1000 lines of code, this "prefix everything" comes in handy."
It's a shame that these prefixes/naming-convention madness will endure forever
The M prefix for instance variables echoes back to "me". In all my classes, I use me-> for any instance variables, so I don't see any benefit to prefixing them all with me. me->s_data is clearly and unambiguously an instance variable with a structure. By using M, I think you've introduced an unnecessary complication. Statics, I'd like to use the class=> format, but it does make the variable name awfully long. At the moment, I use the convention that if it's static, it's prefixless, but I don't really like that. Maybe U for universal! Then, within a method, you'd have, for example with structure, is_, es_, cs_, ls_, me->s_ lcs and us_ variables. Scope and context clear. ( for changing, I use x, rather than c, primarily as c for me has meant "constant" for over twenty years... ).
For tables, I follow what SAP have done in a number of places, specifying the type of the table. So, LT is a local standard table, LTH is hashed and LTO is sorted. Strictly, there's some issues here as well - what would I use for a generic table.
I think we can argue and discuss the exact preferred, but, ultimately, if all programmers within a company/project are using the same standards - with standards as rigorous as you present - then it doesn't matter too much if we use r_ for reference variable, or o_. A new developer will quickly adapt to the site standards.
Great blog, I'm glad to see someone taking the time to bring this up. Most of my conventions are based on what I call 'majority rule': Search through SAP standard and see how it's done most of the time. That said, my convention differs from yours by two type prefixes: 'V' for variable and 'R' for references, as opposed to D and DO. 'D' is rare, and 'DO' I have never seen. Any particular reason for the choice of these?
In response to Matt: I use the M_ prefix or lack thereof can distinguish private/protected from public attributes (which have no prefixes in business classes). It's a quick visual indicator before changing something whether it could be in use outside the class where it's less likely to be found by the where-used search.
On a more general note, naming conventions can be a big topic, and it would be interesting to see a project to get a global standard together. There's so much more that can be standardised, from table types to table names (should one suffix them with a plural 's'? - as in ZUSERS or ZUSER?). Or some of the more esoteric stuff like persistent class reference fields in tables (*_OID/CLS or *_GUID/CLASS?).
Might also be worth mentioning that SAP have published an OO naming convention in the help:
http://help.sap.com/saphelp_nw70ehp1/helpdata/en/92/c2b084bc1d11d2958700a0c94260a5/frameset.htm
Maybe docupedia might be a platform for a bigger project?
Cheers,
Mike
I suppose for the really geeky look, we could have our private attributes as __s_stuff, and protected as _s_stuff. 😉
With SmartForms, I set up a structure for all the elements not in the interface, and the workareas for any loops, and a reference variable. I use the getter methods of the class to populate the structure.
But I do prefer Adobe...
My alternative is Adobe but to customers the price acts like beergoggles: it makes SapScript look sexy.
An additional twist in workflow is that business classes can be directly exposed to the end user via the log, so public attributes really are public and have a very deliberate purpose, e.g. a DOCUMENT->CREATED_BY readonly public attribute populated at instantiation provides useful information to the end user and the administrator. That makes them happy, and who am I to argue with that? 🙂
readonly attributes are perfectly acceptable and also available in more modern languages like scala where "immutable variables" are a big win.
a multiude of getter/setters on the contrary is oo done wrong. it's about methods "doing something" not getting/setting stupid scalar values.
PERFORM alv_layout.
PERFORM alv_sorting.
PERFORM alv_field_catalog.
PERFORM alv_output.
All those are interacting with global variables. 99% of my form routines dont have parameters. Form routines do not hide the global variables inside a form.
If i need reusable code in a report i put them in an accompyning class. If the code is worth to be global for all or for a lot of reports, i'll put the code in a general class.
I only prefix internal tables to distinguish them clearly from database tables, and i prefix workareas for those tables.
Nevertheless, a great blog. I wish i could introduce something like this here. We have naming conventions, but there are always discussions around them.
I suppose it might be ok, so long as the "helper" variables are local, but if your helper variables are global as well, then any enhancements will be more prone to failure, and therefore potentially more expensive.
Regarding reuse - I always try to code for reuse. I've occasionally found that I've developed a class for a specific task, thinking that it probably won't ever be used anywhere else, and then some enhancement/new requirement comes up, and I've already developed 75% of the code.
This avoids side effects...its impossible to use a global variable by accident and it avoids me to prefix everything with g as i only have those 🙂
Forms are no better then sections in cobol...
It seems that I have stirred up a hornets' nest by this blog. Instead of replying to each response individually I would like to summarize the current discussion (for the first time) and answer you all together.
Reinis Dzenis: "I would actually imply that there is kind of better way to make code more readable than "prefix everything" approach and that would be properly structuring the code."
REPLY: Naming conventions are not a substitute but a supplement for good structured coding. If we agree that no prefixes at all is bad then where to set the upper limit? 80% Prefixes? 95% ? Im am convinced that we can define simple and unambigous prefixes covering 100% of all possible variables in ABAP. And we should not forget: ABAP is a hybrid language and by no means as pure as Java.
Matthew Billingham: Text of message:
"there are no big problems to quickly figure out variable scope and meaning anyhow"
But if it's there in the prefix, then you don't even have to figure it out. It's totally unambiguous.
REPLY: None, because that is my conviction.
Matthew Billingham: "I'm puzzled why you have a seperate prefix for references to classes and references to interfaces."
REPLY: The little advantage of this convention is that if you are aware that the static type of your reference variable is an interface you do not try to call methods only defined in the implementing classes. I agree that this distinction is questionable.
Mike Pokraka: "That said, my convention differs from yours by two type prefixes: 'V' for variable and 'R' for references, as opposed to D and DO. 'D' is rare, and 'DO' I have never seen. Any particular reason for the choice of these?"
REPLY: You can find 'V' frequently in the formal parameter names of routine (in the standard). In addition, I think 'V' is used for constants as well. 'R' immediately triggers me to await ranges. All reference variables to classes/interfaces and data objects are objects (= 'O') in my opinion. In order to distinguish data objects (which are clearly different from class objects) they have the prefix 'DO'.
Public Attributes in Classes: They are frequently used by SAP (e.g. RE-FX classes => CL_RECN_CONTRACT~IF_RECN_CONTRACT~MS_DETAIL). However, they should be defined as read-only.
Continued.
Best Regards
Uwe
2. Prefixes actually encourage bad programming style. For example, in 99.9% of your code you should never see a prefix starting with 'G'. Global variables are bad bad bad. Prefixes are just trying to cover up their badness.
Rather than spending your time worrying if it should be gtx_i_p_variable... clean up your code so it's not an issue.
3. I believe there is an anti-pattern to the type of prefixing always used. Don't bother with prefixes for your most common stuff (should be method/form/function level variables in preference to globals). Then use prefixes where it is necessary for exceptions. Use G_ as the exception to let everyone know you did something bad.... Then justify why you used it.
4. I also find that prefixes clutter up the code and I actually lose the real variable name. There are too many git_ lit_ lv_ in code that it becomes unreadable.
Thanks.
1. I AM convinced that the lack of concise naming conventions is a bad thing.
2. Whenever I encountered bad programming in the past 10 years a hallmark was the absence of concise naming conventions.
3. ?
4. In my case readability of coding is highly linked to the usage of recognizable naming conventions.
Regards
Uwe
I agree with paul in every point, it *is* actually an anti-pattern.
Because the code is hard to read you try to improve it by introducing prefixes instead of restructuring/refactoring it into smaller, more concise parts.
You should assume everything is local, until otherwise stated (G_ as an exception).
You should assume the name tells whether it's a multitude of things, e.g. a table.
The syntax clearly denotes whether it's an object->method( ) call or if it isn't, there is no semantical benefit at all in this prefix-stuff.
Yes, yes,yes!!!!
1) I had one doubt after skimming your text: why XT_ for changing tables, instead of CT_ ?
2) In some cases, I would use some other prefixes. We'll never agree on the same ones unless SAP has official rules (which I suppose they do internally, even if they have evolved over time). Does anybody now if the SAP Press book "Official ABAP Programming Guidelines", by Horst Keller and Wolf Hagen Thümmel, available in October, will cover this?
, there are no internal standards!
Even if SAP have official rules, they'll never enforce it. Using consistent, comprehensible prefixes is one tiny step toward producing good ABAP programs, it would be a MASSIVE mistake to think that that is all there is to it.
Without standards we're lost. Think about what things like RJ11 make possible.
It has everything to do with the fact prefixes exist/are used and, minimally, what letter represents what.
So, AMEN and thanks!
We even argure that if you follow all the other rules for good programming (e.g. lean methods with lean interfaces) exaggerated naming conventions can have a negative effect on the readablity of the programs.
At TechEd 2009, I am open for discussions after my presentation CD103 (http://www.sapteched.com/usa/edu_sessions/session.htm?id=322) and in a dedicatet expert networking session (http://www.sapteched.com/usa/activities/session.htm?id=237).
"We even argure that if you follow all the other rules for good programming (e.g. lean methods with lean interfaces) exaggerated naming conventions can have a negative effect on the readablity of the programs." That's a very good point. Recently I had one of my programs reviewed. The reviewer said I hadn't used enough comments. I maintained that given the names of the methods I'd used, it wasn't necessary:
One of our guidelines regarding comments:
Rule 4.10: Comment Meaningfully
Comment your implementations in such a way that the comments describe why something
is done and not how.
Ideally, the source code largely documents itself if appropriate names are selected (see Section about naming). This is the best way to document the aspect of “what happens in this program section.” If this is the case, additional comments that only describe obvious behavior are superfluous and don’t contribute to the comprehensibility.
LD r,3 ; load register r with 3
🙁 🙁 🙁
You mention that technical prefixes are left up to each organisation. The alternative is that each developer chooses whether to use prefixes or not. The point of this blog is to try to get "customer" developers to unify their use of prefixes - it could be argued that this will be impossible until such time as SAP itself imposes a standard for prefixes on it's internal developers.
Do you think SAP will ever try and enforce any sort of gloabl naming standards on it's internal developers or is this considered impossible?
Cheersy Cheers
Paul
Yes there are internal global naming standards of SAP for program internal prefixes and there is a respective check in Code Inspector as of Release 7.0, SP13.
We present (and discuss) this standard in the Appendix of our book. But to be honest those guidelines for prefixes are not exactly brilliant. Conventions for types are missing, "v" stands for elementary data type (mixup of type and changeability), "g" should be reserved for global declarations but is used for static attributes also, "u" is used for using parameters instead of "i" (same in the blog above, why?), ...
These naming convention clearly show the difficulties that arise if you try to express complex technical information in prefixes, especially, if you try to keep the prefixes seemingly simple.
I.m.h.O., to accommodate all technical
information (as data type, context, changeability, visibility, parameter type, transfer type, etc.) uniquely in a prefix, you require a notation with at least 3 digits for a meaningful combination of the individual dimensions. In this notation, each desired aspect must be assigned to a fixed position and be always specified in full. But then what about refactoring if only one aspect of your entity changes?
What we really need are tools that tell you what you need by a simple mouse over in the editor (and an overall turning away from monolithig programming, of course)
Best
Horst
Is it possible to still access any of those TechEd session?
Every link seems to be broken by now...
I want to ask how do you call your own types? Is it any naming convention for them?
I use the following simple naming for own types:
TYPES: BEGIN OF ty_s_outtab.
TYPES: exception TYPE lvc_status.
INCLUDE TYPE knb1 AS customer.
TYPES: END OF ty_s_outtab.
TYPES: ty_t_outtab TYPE STANDARD TABLE OF ty_s_outtab
WITH DEFAULT KEY.
I used to distinguish local from global type definitions using 'L_' but - to be honest - it looks somewhat odd therefore I dropped this prefix for local types.
Regards
Uwe
Great blog and great discussion.
I recently realized something about names of types and variables. It is legal to use the same name for both the type and the variable.
Example:
TYPES: BEGIN OF customer,
name TYPE string,
END OF customer.
DATA: customer TYPE customer.
For developers not using prefixes, this might be useful. I never though of it before because I've been using prefixes and it is not allowed in e.g. Java or C++ (I think).
Has anyone used this convention? Are there any reasons why this is not a good idea (other that preferring prefixing in general)?
If this is not a good idea, what would be a better option? Using a prefix for the type only (ty_customer)?
Regards,
Christoffer
To prevent confusion of the viewer, it is recommended to use different names for different entities, and particularly to not use the name of data types also for data objects. Exceptions from this rule can be cases in which the meaning of a name is absolutely clear, for instance, for the declaration of a helper variable:
DATA i TYPE i.
Conversely, however, it should never occur that a data object has the name of a data type that is not the type of the object:
DATA i TYPE f.
DATA tadir TYPE trdir.
Such declarations are confusing and therefore dangerous!
Maybe we should start a competition like this http://www.ioccc.org/ but for ABAP.
My conventions for TYPES definitions are (almost) the same as I described already:
" TY=types, S=structure, T=table type
TYPES: BEGIN OF ty_s_customer.
TYPES: name TYPE string.
TYPES: END OF ty_s_customer.
TYPES: ty_t_customer TYPE STANDARD TABLE OF ty_s_customer
WITH DEFAULT KEY.
DATA:
gs_customer TYPE ty_s_customer,
gt_customer TYPE ty_t_customer.
To be honest I am not sure about whether we should or need to distinguish between local and global TYPES definitions, e.g.:
TYPES: BEGIN OF lty_s_customer.
...
TYPES: lty_t_customer TYPE STANDARD ...
Even though the prefix LTY (L=local, TY=types definition) looks a bit odd the distinction makes sense because then you avoid that a global definition might be "superseeded" by a local one.
Regards
Uwe
I hope all in well. Funnily enough I did some work for Sprungli back in the day.
Out of interest why do you use gt_s_ say for a global type that is a structure? Wouldn't the data type that is pointing to the global type be declared in such a way that it's evident it's a structure?
IE:
*<= Global Type
types: begin of gty_sales_info,
vbeln type vbak-vbeln
posnr type vbap-posnr,
erdat type vbap-erdat,
end of gty_sales_info.
*<= Global Structure
data: gs_sales_info type gt_sales_info.
By doing is this way you also use the same global type to declare an internal table if needed?
*<= Global Internal Table
data: gt_sales_info type standard table of gt_sales_info.
Cheers,
Neil.
Please be aware that there is a big difference between Sprüngli (www.spruengli.ch) and Lindt & Sprüngli (www.lindt.com) where I am working (in Kilchberg).
You are right that there is no need to have the type (field, structure, table type) within the name of the TYPE because the variables defined using this type have the prefix already in their names.
On the other hand why should we make an exception from the (general) rule? And if we are working with lots of TYPE definitions within the same programming object the differentiation just help to find the correct TYPE definition for your data variables.
Regards
Uwe
Please see my answer I gave to Christoffer.
Regards
Uwe
Hi Uwe,
My comment is unrelated with the content of this blog but I notice that your blog layout somehow become untidy with html tag all over the place.
I am quite sure the last time I check on this blog the layout is still neat however as of today when I'm using firefox 14.0.1 and I.E. 8, the blog layout is unreadable for some section of this blog.
Maybe you want to take a look at it.
Thank you.
Sadly, the upgrade to the new SCN had dstroyed the content of this blog, which I find very sad, as I think this is a really important subject, as can be seen in my comments above.
SAP - in the shape of the SAP press books - advocates naming things whatever you feel like, which can be seen in standard SAP code, but most companies running SAP tend to adopt a naming convention using some form of technial information in the variable name e.g. LD_ for a local elementary data type or LV_ or one of a million other variants.
SAP may say that no-one uses anything except OO programming these days, and even if that was true, which it isn't (I do by the way) there is heaps of legacy code to be maintained.
Given that, it would be lovely if there is SOME degree of consistency, instead of 100,000 different programmers each doing the same thing a different way.
Excellent topic!
SAP could provide an authoritative guide to naming objects based on this topic and in the comments, so it's much easier to convince customers to use a more appropriate naming rule.
They did, some 4 years ago already:
Official ABAP Programming Guidelines. of Wolf Hagen Thümmel, Horst Keller - by SAP PRESS
Please ignore everything I said in my comments above. At the start of this year, I began developing without prefixes (except for specific cases to be mentioned below). I am now utterly sold on it. I also tend to put my DATA statement just before the first use of the variable instead of having them at the top.
The only prefixes I now use are:
i_ for importing parameters
e_ for exporting parameters
x_ for changing parameters
c_ for constants
_ for static methods and attributes
me-> for instance methods and attributes
This Damascene conversion is probably due to me beginning to do Java coding again.
I have been thinking about this for five years. As mentioned above my biggest problem was 100,000 ABAP programmers each naming variables in a different way.
I have come to the conclusion that making the program read like Plain English is the highest priority as in Donald Knuths "literate programming". That's Donald Knuth, not Donald Duck. If Donald Duck wrote a program it would come out "quack quack quack".
When a prefix can contribute to a human getting less confused whilst reading the code, it's great. If a prefix gets in the way of that aim, it is bad.
Robert Martin in the "clean code" book says that we are authors and that your program should read like a newspaper.
SAP itself clearly has no internal standards even to this day. I was importing a few OSS notes the other day for a function that came in with EHP5, and though the code was all in classes and methods you still had LS for a local structure, GS for a global structure and GT for a global table ( CL_MMIM_MMA_2 / method READ_GT_MAA_LOCKTAB_QTY). I did find that a lot easier to understand than some of the standard SAP programs from 20 years ago I have to debug. I think the author of the new code may have read this blog five years ago.
I also read somewhere that the original concept of "hungarian notation" where you add a prefix to a variable name was all a horrible mistake. Someone at Microsoft wrote a research paper where the introduction sounded like they were in favour of such things, but the body of the paper and the conclusion came down against them. A lot of people only read the introduction, concluded prefixes were therefore good, and it became company policy all over the place.
I would like the thirty character limit on variable names increased, in Java you can have very long names. 30 characters seems like a lot, but often I am forced into abbrievations or acronynms. On the plus side, it is good that the names of fields in DDIC tables can now be as long as the names in structures.
Going back to when can a prefix possibly make things clearer, one area is when maintaining monolithic monstrosities, which a lot of us have to do on a day to day basis. In such cases I have come across "OK_CODE" defined as a global variable, a parameter, and a local variable, and you don't know whether you are coming or going.
If you have OO programs where you can see all the code of a method and the signature at the top all on one screen the problem of having to guess what the scope is starts to melt away.
I also like Matthew's idea of declaring the variables just before they get used, I had always put them at the top because "that was the way we have always done things". The SAP compiler does not care where you declare the variable as long as it is before the first usage, but a human cares very much when reading the program what the variables nature is.
Also the ABAP language makes it easier to write statements that look more like English with the improvements that have come with each release e.g. functional methods at operand positions.
On the subject of declaring variables just before they are used, don't forget ABAP 7.4 supports inline declaration. ABAP News for Release 7.40 - Inline Declarations
Yep, and we have also enhanced the guidelines for these:
http://help.sap.com/abapdocu_740/en/index.htm?file=abendeclaration_inline_guidl.htm
(B.T.W., the sentence there
is not the best translation of the original statement 😕
It should read:
However, since they they work like a short form of a directly preceding declaration statement in front of the statement where they are specified, the guidelines
for declaration statements must be followed. )
What about the lifetime of those inline declared variables? Is a variable declared in a loop visible outside the loop once the loop has finished?
-> unfortunately, yes
The effort of introducing real local contexts into good ol' ABAP simply was too large and it was not tackled when introducing the inline declarations 🙁 .
(For this reason, there are also strange rules for expression-local declarations as they can be achieved with LET http://help.sap.com/abapdocu_740/en/index.htm?file=abaplet.htm, those are a kind of pseudo-local).
I was just watching some of the SAP tutorial coding videos on YOUTUBE about how to create ABAP Managed Database Procedures.
The irony is, at just the instant I was becoming convinced not to use conventions like IV_ for an importing elementary variable, or IT_ for an internal table, in all the current examples coming out in these SAP videos that is exactly the convention they use.
Standard SAP programs never used to use any naming conventions, another irony is that the training videos coming out of SAP now being posted online now have the IV_ type of naming conventions when they did not before whilst us poor "customers" who used to use such naming convetnions, are moving away from them....
SAP was never a good example:
We have used a set of naming conventions very similar to this for many years. We "inherited" them from an SAP Platinum consultant on our initial 4.6C implementation. At that time ABAP Objects was in its infancy, and we didn't address ABAP OO in our standards. I am finally getting around to updating our naming standards for OO, and I have a simple question: what is the significance ot the "M" prefix for class data? Where does the "M" come from? What does it stand for? I can understand "G" for global and "L" for local, but "M" for class I don't understand.
Cheers,
TerryB
M is the prefix for member attribute. I don't use prefixes which denote scope or type at all, but this one seems particular pointless, as we can already use me-> (which I do use when referencing attributes and methods of the current class).
It was a huge jump for me to move from procedural to OO programming, so I am not surprised you are still puzzled after SAP pushing OO programming from 4.6 (2000) to date.
In procedrural programming you have global variables that can be changed anywhere in the program (these are BAD) and local variables which only exist inside the procedure (method).
In classes however you also have "member" variables (oh errr, sounds a bit rude) in which the scope is either the class in question (static) or an instance of the class in question (instance).
If I have lost you already by talking about OO terms I would recommend looking up the basics on Wikipeda, and then some really good books on OO programming - Head First Design Patterns or Clean Code spring to mind. They presume a certain knowledge of OO programming - a knowledge that in 2015 is vital, even for ABAP programmers.
Classes should be small in scope i.e. do only "one thing" and so a member variable is one that is shared between the methods of that class. At the start that seemd just like a global variable to me, but after a lot of thinking I now it is anything but, as ulinke a global variable the value cannot be changed by anything but only within the instance of the class.
Going back to naming conventions I am now going crazy trying to name input / output parameters and variables so I can make a line of code look like an English sentence
e.g.
the_rule_is_vaild_if->the_fish( has_scales_that_are = green ).
Look up a gentleman called Donald Knuth on the internet to see his views on "literate programming".
Robert Martin said "we are authors" - people look at our code and should be able to read it without having to have their brains melt.
The new ABAP routines in 740 make the boiler plate code less readable, but if someting becomes so obscure you cannot tell what it is doing, you can aways wrap it in a hgher level method using English terms.
Cheersy Cheers
Paul
Also back in the time when 4.6C came out ( just before 2000) a lot of consultants, even "Platinum Consultants" were what could be described as "one page ahead" i.e. they were one page ahead in the SAP textbook than their clients, earned twice as much as the permanent employee, and the consultant company charged five times as much.
To be fair, maybe "platinum" consultants in 1999 were two pages ahead.
Hello Terry
The advantage of using the "M" for members, i.e. instance and static attributes of a class or interface, that you keep the very same syntax as for local and global variables.
Looking at rather modern classes in SAP R/3, e.g. CL_USMD_GOV_API or CL_USMD_CREQUEST_API (SAP-MDG) you will recognize many of the naming conventions described above (yet less stringently applied).
This does not imply that SAP developers follow my recommendation but, on the contrary, I took the best from SAP that I could find when I assembled these naming conventions.
For a SAP-MDG project I implemented the Cross-Entity BAdI IF_EX_USMD_RULE_SERVICE2. Below you see a custom method whose signature was copied from the single interface method DERIVE. This signature "follows" my naming conventions which makes it perfectly readable (and understandable) for me.
The coding shows the consistent use of my own naming conventions, e.g:
mac_assign_component_and_fill:
mc_fname_kautb <ls_record> <ld_field> me->mo_const->mc_marcpurch_kautb.
Even without knowing the details of this macro it can be interpreted based on the naming conventions:
Looking at coding generated for calling BRF+ rules you will find - naming conventions.
CONCLUSION:
Whatever naming conventions you use apply them consistently for global, local and class variables.
Best Regards
Uwe
Mr.Uwe,
I spend a lot of time in my job debugging standard SAP code and I have come to the following conclusion,
At the time your blog was first published - August 2009 - SAP clearly had no internal conventions at all for variable names. Every single standard SAP program went its own way on this, just like the many thousands of customers.
I can only presume a vast number of SAP staff read this blog, because now there do seem to be conventions in standard SAP code and they are remakably similar to the ones you proposed.
In your comment above you modestly say you cannot possibly have influenced SAP but I think you have.
The irony is that in the intervening period many programmers - like myself and Matthew - have moved from thinking such prefixes are a good thing to doing away with them in an attempt to make programs look like English. I still use them in the monolithic legacy code base I have to mantain, but not in OO classes/methods.
Nonethess in my early comments on this blog I moaned about the lack of a worldwide standard for ABAP programmers to follow (the official standard being "do whatever you want") and I would be a giant hypocrite if I now moaned about the company SAP itself adopting such a set of standards - your standards.
What I wanted was at least two programmers out of the teeming billions to be doing the same thing the same way and now that has happened, SAP itself behaving consistenty at last. The proverb here is "be careful what you wish for".
Anyway, well done. You have made your mark on the world and that is all any of us can ask for - though I would end by quoting Woody Allen as follows:-
"I don't want to achieve immortality through my work - I want to achieve immortality through not dying".
Cheersy Cheers
Paul
And then here ABAP Modern Code Conventions it's pointed out that Horst Keller's book Official ABAP Programming Guidelines. of Horst Keller, Wolf Hagen Thümmel - by SAP PRESS has minimised prefixes to usage (i.e. dropped typing information). This is pretty much what I use, except for x_ for changing, c_ for constants and I suffix _ty for types for readability.
A couple of other points. I find <L_some_field_symbol> in a method to be pointless, since field symbols in methods are always local. Not as bad as <FS_....> or PERFORM f_... which I see regularly in new code at one of my clients. Unfortunately, I don't have the authority to harangue them about this. I just die, inwardly.
Also, I find
mac_assign_component_and_fill:
mc_fname_kautb <ls_record> <ld_field> me->mo_const->mc_marcpurch_kautb.
really ugly. While macros have their place, I'd probably write this as a method. Though I rarely use ASSIGN COMPONENT, even in disguise. I create a structure with the fields I need and then use.
LOOP AT dynamic_table ASSIGNING <record>.
MOVE-CORRESPONDING <record> TO structure_with_my_fields.
...
ENDLOOP.
In my book on ABAP Programming you will notice I still used the Hungarian Notation for the variables in my code samples. (As I said the term Hungarian Notation is a total misnomer).
I have now started writing the second edition and am now going through all the code changing the variable names to drop the prefixes. This makes one think long and hard about the name to make sure it reflects what the variable is used for.
In my BRF summoning code sometimes I am finding by being forced to change the name to something more descriptive I can drop the comment in the line above where the variable is used, because the comment now is just an echo of the line of code, dropping such comments is wonderful.
Combined with the inline declarations you get in 7.4 the code is getting more and more like plain English all the time......
It took me some time to switch to data declarations just before the variable is used for the first time and to drop prefixes - but now I wonder why it took me so long!
I was going through some old code yesterday and came across a variable called r_steering. I spent sometime puzzled why there was no returning parameter in the method signature... then I realised it was a instance attribute with an....urg... prefix. Somehow at the time of writing I though that the information that steering is a reference to an instance was important... Quickly, before we upgrade to 7.4 and lost the ability, I renamed the variable and chose the refactor option to change all references to it.
The prefix was totally pointless, misleading, added no value.
Why do we change our minds about this?
To show how sad I am I will give a quote from "Star Trek : Deep Space Nine".
In one story Quark's brother has to share a room with him, and after a while the brother announces he cannot stand listening to Quark speaking aloud in his sleep at night.
Quark : Why not?
Rom : Because all night long, all the time, you are always thinking!
I am guilty of this hideous crime also, even in my dreams, though I do not speak aloud about SAP programming whilst I dream, or my wife would have killed me by now.
Back in the waking world, it is difficult to come to terms with the fact that what you have been doing for years e.g. prefixes, is bad, and then make a dramatic change going forward , but as someone somewhere once said "you have to adapt to survive", and as someone somewhere else once said "the sleeper must awake:.
Don't be so hard on yourself 😉 I wouldn't call it "bad", more like "no longer appropriate".
Naming prefix conventions added some structure to a language with limited structurability (yes I just invented that word). It made perfect sense in a 4000 line report with a boatload of PERFORMs and another 8000 lines of INCLUDEs. Modern ABAP has opened the possibilities and replaced much of the need for naming prefixes.
I think discretion is best: when tinkering with old style code, keep with the existing prefixes. But if some of it can be pushed out into a class, the class can use proper 'clean' names.
Structurability.
You're suggesting old-style coding is like chugging Vodka and these days we're flying on rocket fuel?
Also amusing that it's on pubs.acs.org 🙂