ABAP Modern Code Conventions
Introduction
Coming from a computer science background and having learnt ABAP on the job in a SAP consultancy, I always wondered why there are so restrictive naming-conventions and why every customer has their own custom ones, each apparently trying to trump the other with even more detailed naming-conventions for every little technical possibility… To me it seems to be a SAP-speciality that has vanished everywhere else (or so it seems … hello cobol legacy applications, hello hungarian notation)
Having read this interesting Blog post: Nomen est omen a while ago and having to tackle a big custom code-base ourselves (with our own inevitable hardcore-detailed naming conventions and our own fair share of technical debt …) we discussed what to focus on in the future.
Goals: Simple, short & concise code conventions that ease development and make the code easier to read.
After all, you as a developer are spending about 70% of your time reading & analysing existing code. You want that code to be short and readable. And you don’t want to constantly lookup naming conventions, do you?
How much code do you fully understand from top to bottom? Can you analyse & memorize only 100 lines of unbroken, unknown code and estimate the implication of new changes? I don’t. I feel big relief if that code is broken up into as many form-routines (functions, methods, whatever) as possible: We dearly want Seperation of Concerns.
Decisions
- No global variables (except where required… Hello, dynpro-binding): Local variables are the norm
- No technical duplication of information already explicitly & neatly specified in the type-system (we love statically typed languages and despise dynamic languages, dont’ we?). Instead focus on semantics, readability and meaningful names.
- Keep it short: Form-Routines, Function-Modules and Class-Methods are limited to 70 lines of code/LOC.
From all we’ve heard this should automagically lead to better (not good) maintainability
Some Rules derived from these decisions:
- Since every variable is local there is no need for “My prefix hereby tells you that I am …*fanfare*… local!”.
So no more L_ prefix. If you see a variable like “flight_time”, it is local. Spare prefixes for special occasions, to emphasize. - Global variables are a special case, use the G_ prefix to discriminate them as the despicable things they are.
Your brain/eye instantly catches these special prefixes, they no longer disappear between all those other L_ … - Class-attributes are like local variables, they are class-local, they are not global.
As such they don’t have any prefix either but you may choose to use “me->attribute” to clearly indicate attribute-access. - Use meaningful constants like co_open_in_external_window instead of ‘E’
It does not matter whether these constants are defined globally or locally, just use a “CO_” prefix to specifiy them as being a constant.
If you have an interface that only contains constants (an ABAP design pattern to create nice container for constants), you may omit the “CO_” prefix altogether. And yes, you may argue this constant-prefix too š - If you define types it does not matter whether the type-definition is local-only or globally, just use “TY_” for types.
- The most controversial: The variable shall have a meaningful name, no abbreviations and shall not contain technical information that is already specified in the type-system. Focus on the semantics!
So no more “ls_sflight” and “lt_sflight” but “sflight_entry” and e.g. “sflight_tab_delete” (emphasize on “delete” to describe what entries are contained in the table and why).
You may argue “So you traded lt_ for the _tab suffix and actually gained nothing, well done.”.
In some way or the other you have to declare a table as being a multitude of things, it does not matter if you use the typical s-plural suffix for “sflightS” or use a “_tab” suffix, the important thing is to focus on its meaning and reserve prefixes to emphasize on important things (hello ugly globals…).
Besides, ABAP itself is already shouting in your face whether that variable is a table/structure:
READ TABLE x, LOOP AT x, x-comp = ‘foobar’ etc. you really don’t need anything more 90% of the time… - Use mathematical notation instead of abbreviations that make the code harder to read: <= is way more intuitive than LE.
Just use normal math-operators that you’ve already learnt in school. I often hear that NE and LE are perfectly reasonable and understandable but this argument always comes from guys with decades of experience. I think the more simple way (not easy) is always to be preferred, there is no point to distinguish yourself from lesser experienced by using voodoo’ish notation…
TL/DR: This leads to the following inevitable naming-convention-matrix:
Prefix | Comment | |
---|---|---|
Locals | NONE | |
Globals | G_ | |
Field-Symbols | <NONE> | Really ugly: global Field-Symbols: <G_XXX> |
Atttributes | NONE | Use “me->attribute” to distinguish from locals if necessary |
Constants | CO_ | No distinction local vs. global (Omit prefix in constant-interfaces) |
Types | TY_ | No distinction local vs. global |
Form Using | I_ | Concentrate: Using = Importing/Input, no need to distinguish |
Form Changing | C_ | |
FM Importing | I_ | Try by reference |
FM Exporting | E_ | Try by reference |
FM Changing | C_ | Try to avoid |
FM Table | T_ | Avoid! |
Method Importing | I_ | Try by reference |
Method Returning | R_ | |
Method Exporting | E_ | Try to avoid |
Method Changing | C_ | Try to avoid |
Select-Options | S_ | |
Parameters | P_ |
This table is hopefully concise enough, we actually printed it on 1 DinA5, instead of the former 2 DinA4 pages.
Before starting the eagerly awaited flame war, please consider that these conventions follow those described in the book Official ABAP Programming Guidelines. of Horst Keller, Wolf Hagen Thümmel – by SAP PRESS (p. 208ff). Even if the internal SAP conventions really hurt my eyes and every SAP development team seems to use their own even more cumbersome conventions, Thank you Horst Keller for these guidelines.
No conclusion yet, we just started with these conventions and still figure out how to transform the existing code-base in a pragmatic approach…
Tools
Code-Inspector Test based on CL_CI_TEST_SCAN to limit the allowed Lines of code (Will release that soon…)
We are using smartDevelop but still need to figure out a good transformation-strategy.
Thank you for your attention, any comments appreciated.
Hello Kai,
what are you creating?
As a developer using a consistent naming convention with readable code, would I be able to continue work as before? I feel your rationale is not sound:
I prefer the rules in the referred blog.
my 2 cents.
JNN
What do you mean?
Functional programming requires the ability to treat functions (ie: methods, forms, etc.) as variables and pass them around. As far as I know, ABAP provides no way to do this.
You can do some pretty neat-o things in functional languages such as Scala, Groovy, Javascript, etc...
For example... Declare two variables that are actually functions:
var x = function(a){ return a; };
var y = function(b){return b; };
Then you get the following:
y(x("asdf")) == "asdf"
Since you can pass functions around, you will work with map and other higher-order functions which are the prime reason every modern language (java 8) is including functional aspects... it's really great.
Here is a wonderful document explaining functional programming to ABAP people.
http://scn.sap.com/community/abap/blog/2014/02/18/javascript-for-abap-developers
I had a look at the slides about functional programming in JavaScript and instantly tried to translate this into ABAP. Below you see my sample program, both in the imperative and the functional style.
The only thing I could not achieve in ABAP is a so called "ternary operator" which languages like JavaScript have but languages like ABAP do not seem to have,
There you can say RETURN (n==1) ? a;do(function)
If N is equal to one then "A" is returned, otherwise the result of the function. That is just like an IF statement you may say, just harder to read. I would say so to but in the slide it is claimed that an IF statement is the work of the devil as it makes you think the value of N is somehow important.
To make up your own mind, have a look at the slides - especially number 7 about functional programming - and then look at my program below which is my go at writing an ABAP program in a functional style.
If anyone can think how the new constructs in 740 can plug the gaps and make ABAP more functional (if that is indeed a good thing) then I am all ears.
Here is my code on the Cornish Pasty Site:-
https://paste.ee/p/6mXUG
Hey Paul, could you post that code to Paste.ee or other code-service (pastebin is blocked in our company for whatever reasons...) and then link to it?
I just submitted it to the pasty web site. I called it "Functional programming in ABAP test by PDH"
https://paste.ee/p/6mXUGhttps://paste.ee/p/6mXUGhttp://
is it as simple as that?
In the UK we have cornish pasties which are a very fine food indeed.
Cheersy Cheers
Paul
LOL "Here is my code on the Cornish Pasty Site:-"
What you're describing is the idiomatic functional way of programming: using recursion (most functional languages do tail-call-optimization so that this form of recursion does not blow your stack), accumulating intermediary results in the input-parameters & having no global state whatsoever. So you got purely (more or less) mathematical functions.
In languages like Java8 that only adopt functional aspects but are not functional themselves (see haskell for a pure functional language), you can use most of the functional goodness (see map-function) without being forced into a functional programming style.
Hey Paul,
I think you're missing the point of functional programming... It's not just using recursion instead of loops...
You're missing functions as first class citizens (ie: can be assigned to a variable), anonymous functions and many other important aspects of functional programming.
It cannot be done in ABAP at all.
I was thinking of means to define a custom function type in ABAP. e.g. for function eat taking a Cat With Prey and returning a Cat With FullTummy.
Actually we could use an ABAP interface method with the signature of the function for the definition, but we would then miss the option to pass a function type parameter by name. This is not a minor/incremental change in a language.
The essence of functional programming is delaying side effects as long as possible (cf. J. Suereth [Scala in Depth]).
regards,
JNN
I understand that ABAP was never intended to do this sort of thing - you need a change to the language such as the recent changes to Java which now includes "Larry the Lambdas" to enable functional programming.
e.g. we do not have a ternary operator in ABAP and that a ternary operator is alleged to be better than an IF statement for some reason, though I can't see why.
Anyway, just because something is impossible doesn't mean I am not going to try and do it anyway even if I fail every time / miss the point etc...
How about using the IF_CONSTRAINT interface? You put your function logic in the "is valid" interface (the one that takes in an anonymous data object) of class FULL_STOMACH which implements the interface,pass in the cat object and then say something like:-
CL_ABAP_UNIT_ASSERT=>ASSERT_THAT(
exp = abap_true
act = full_stomach->is_valid( cat ) ) .
I could pass my FULL_STOMACH instance to and from other methods. Is that what we are trying to achieve?
I am sure I have missed the point again, but this sort of thing is so much fun.....
Cheersy Cheers
Paul
What you are describing Paul, is basically the OO means to implement a function. In Scala for example, being a hybrid OO/functional language, at the end of the day their Functions are actually Implementations of OO-Interfaces Function0, Function1, Function2, etc.
But this is happenening under the hood and is a mere way of implementing this *language-feature*. What you are still missing with your OO-solution is 1) the actual language-feature to have real functions and 2) to pass these functions around like any other value.
So at the end, you are missing higher-order functions which are key to functional programming.
BTW, the ternary operator is just sugar, what you're really after are conditional-*expressions*: Scala/Expressions, Not Statements
Higher order functions would be very pleasant. Maybe Horst Keller can tell us if something is planned in this direction.
Haven't we already?
ABAP News for Release 7.40 - Constructor Operators COND and SWITCH
Christian
Yes, you are right. Somewhat clumsy syntax but real expressions after all, very nice!
Hello Jacques,
the conventions are both our own guidelines (Software Engineers should be free to choose what is best for their product/situation, that's why you saw statements like "try to avoid", etc.) and hard conventions that are enforced through our technical-QS & Code-Inspector Tests.
I don't understand "As a developer using a consistent naming convention with readable code, would I be able to continue work as before?" Why wouldn't you be able "to continue work as before"? The rational is that you can more easily & hopefully satisfyingly continue to work, without the burden of over-regulated naming conventions.
Regarding
1.) of course there are class attributes, we treat them like locals without prefix. In modern languages like scala public readonly/immutable variables can be seen like 0-ary methods (no arguments/parameters), another reason not to artifically distinguish them from methods.
2.) Yes, ABAP's type-system is indeed very limited. But this shortcoming does not require you to duplicate the actually declared type information in the names. The power of the type-system & naming conventions are orthogonal aspects, I think.
3.) On conferences & from colleagues that introduced agile software engineering in their companies in the ABAP context, many told us that the rule/guideline with the biggest (initial) impact was limiting the maximum lines of code. This implicitly lead to separation of concerns and somewhat reasonable interfaces. So we decided on a LOC-Limit (currently more of a guideline) and wanted 50. When we went into discussions with colleagues, some had concerns about whether comments & whitespace do count etc. Eventually we ended with 70 as a compromise. As this rule/guideline is not Word of God we feel free to adapt that limit as we progress.
Regarding functional style not being possible in ABAP... i would be content with an InstanceOf-Operator & Generics š
Thank you for your comment
I read that article referenced earlier by Uncle Bob.
In that article he took a Java program and broke it down with a sledgehammer until none of the routines were over two or three lines long.
He got attacked like nobodies business for doing this, loads of people said it was overkill, but I am sure there is a happy medium.
If moving five lines of code into its own method mad the higher level method easier to read then I say it is good, if not don't bother.
Since ABAP isn't designed to support functional programming (yet!) I don't see this is particularly an issue.
I'd like generics too.
Given that a single BAPI call can, annoyingly, cover 30 lines, a limit of 70 can be frustratingly small. I've always opted for "properly modularised" - we know it when we see it, but it's not easy to specify exact parameters for it.
Hello Kai,
I am used to another set of naming conventions (extended naming conventions in SAP code inspector), so it would be a burden to learn a conflicting set of naming conventions. I would need a sound rationale to switch or you would aleniate me.
I do not believe naming conventions ease development. I think they ease maintenance by enforcing consistency in a large code base. And since most of any code base is from SAP anyway, I feel adopting whatever SAP think is appropriate is a good idea.
I do not believe naming conventions can be short with so many development objects in SAP. How do you name packages? search help exits? reports? Data elements? CDS View? Enhancement Implementations? SAPScript/SmartForms and Workflow objects...
They should try to be complete and unambiguous. If they can be enforced (Code Inspector), developers will use them.
best regards,
JNN
Hi Jacques,
our goal was to simplify the naming conventions by stripping anything unnecessary that, in our view, does not help you in producing "good code"(tm).
If your code base consists of function modules with >1000 lines of code each, I understand that you'll want more "consistency in a large code base". We also have lots of these giants...
If you'll plan to cut those massive pieces into smaller parts with hopefully better maintainability and focus on CleanCode, I'll recommend our minimalistic conventions where development beneftis from these 2 major points: simplicity & ease to read.
Naming DDIC-Elements is another different story, we'll tackle this shortly š .
Hello Kai,
I applied your rules to my code (class LCL_STACK).
METHOD push.
APPEND is_ref TO mt_actor_ref.
mv_empty = abap_false.
ENDMETHOD.
METHOD pop.
CLEAR rs_to.
DATA(lv_last) = lines( mt_actor_ref ).
CHECK lv_last GT 0.
rs_to = mt_actor_ref[ lv_last ]. " first retrieve, then
DELETE mt_actor_ref INDEX lv_last. " delete last entry
mv_empty = boolc( lv_last EQ 1 ).
ENDMETHOD.
The updated code (except for LCL_ and LIF..),
CLASS lcl_stack DEFINITION FRIENDS lif_unit_test.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_actor_reference,
code TYPE i,
sap_code TYPE i,
END OF ty_actor_reference.
METHODS push IMPORTING i_reference_entry TYPE ty_actor_reference.
METHODS pop RETURNING VALUE(r_reference_entry) TYPE ty_actor_reference.
PROTECTED SECTION.
TYPES ty_actor_reference_stack TYPE STANDARD TABLE OF ty_actor_reference.
DATA actor_reference_stack TYPE ty_actor_reference_stack.
DATA empty TYPE xsdboolean VALUE abap_true.
ENDCLASS.
CLASS lcl_stack IMPLEMENTATION.
METHOD push.
APPEND i_reference_entry TO actor_reference_stack.
empty = abap_false.
ENDMETHOD.
METHOD pop.
CLEAR r_reference_entry.
DATA(last) = lines( actor_reference_stack ).
CHECK last GT 0.
r_reference_entry = actor_reference_stack[ last ]. " first retrieve, then
DELETE actor_reference_stack INDEX last. " delete last entry
empty = boolc( last EQ 1 ).
ENDMETHOD.
ENDCLASS.
the no-abbreviation policy makes it easier to read, but I am really missing the type information. And, I miss your spec. for local classes and interfaces. I write code like this:
METHOD filter.
DATA(lo_loops) = NEW lcl_filter_loops( ).
DATA lt_trace LIKE it_trace.
ct_trace = it_trace.
WHILE ct_trace NE lt_trace.
lt_trace = ct_trace.
NEW lcl_pattern( it_trace = lt_trace
ii_target = lo_loops )->detect_cycles( ).
lo_loops->filter( EXPORTING it_trace = lt_trace
CHANGING ct_trace = ct_trace ).
ENDWHILE.
ct_loop = lo_loops->mt_loop.
ENDMETHOD.
This code will not be made simpler by breaking it down to smaller pieces and the detailed type information let me read it without checking each method signature (e.g. II_TARGET: importing parameter of type interface, a concrete object LO_LOOPS is passed and its attribute MT_LOOP is populated.
Not all code is simple, and while it is evolving to a better quality, it has to be correct. I think you would achieve your goal of simplicity by enforcing testability, e.g. ABAP Unit tests with some coverage ratio.
I care about naming, but in your example I would probably use lt_delete instead of sflight_tab_delete. Why should I use and reuse the sflight prefix when it should be obvious in the context?
regards,
JNN
powered by ABAP code lighter for SCN.sap.com
Hi Jacques,
thanks for playing around with the suggested convention and your remarks.
Our current Naming-Scheme for local Classes/Interfaces is simply cl_/if_ as there are actually no clashes with global classes to be expected (hopefully......).
Generally I think you don't need any prefix for local classes/interfaces at all, there is no benefit if named properly (somewhat exact and therefore somewhat unique name).
About lt_delete vs. sflight_tab_delete, I would prefer the simple "deletes". Of course there is no need to prefix it with the full "sflight"-context-thingy if the context is absolutely clear. I despise any dogmatism or black/white-rules á la "you have to prefix it with the maximum available information irregardless of context & situation" or "you must not use any macros, ever".
You are absolutely correct that we really need Unit-Tests but this is a different topic.
Kudos for the nice 740 example & the boolc operator btw š
Do your "actors" imply erlang-style MPI?
You wil see my name in some of the comments of the referenced blog.
I was a big fan of the naming conventions like LD_ but that was probably because my existing inherited code base was crawling with global variables and had no naming convention at all, and so I had to make things clear.
Nowadays I quite agree with making the code read like English as much as possible, which leads me to the next point.
Like it or not, all the statements in ABAP like SELECT and LOOP and so forth are all in English, albeit with USA spelling.
With standard SAP code we see how much the mixture of English commands and German routine/variable names works clarity wise. IT has been said that using LE or GE is no good as these are abbreviations of English terms, whereas = or => or =< are mathematical symbols and thus universal.
Presumably one should not use EQ for the same reason.
Have a quick look at domain DDOPTION in the standard SAP system. This is the same SAP who tell us not to use LE or GE.
OK, lets say I agree, I will not use English terms anymore, just symbols.
Off we go, I will code a SELECT statement.
SELECT * FROM database_table
WHERE something = p_this "Rah Rah!
AND something_else >= p_that "Rah Rah!
AND abc <= p_thing "Rah Rha!
AND def IN ('1','2','3') "Oh Dear!
AND ghi LIKE 'THING%'. "Oh Dear Again!
Now I have a horrible mixture of symbols and "voodo" English terms!
In regard to Constants, Horst Keller says that if you have a constant as a global it will only be stored in one location in memory even if twenty instances of the same program are running, whereas a local constant will be stored twenty times.
Here is a method conforming to the above recommendations:-
METHOD something.
*Local Variables.
DATA this TYPE string.
this = zcl_class=>bingo.
that = zcl_class=>snork.
ENDMETHOD.
Now I quite agree with Robert Martin about short methods, but they have a horrible habit of expanding unless you keep them in check.
In the above method THAT is a member variable, THIS is a local variable. If the DATA statement creeps out of sight the scope becomes less obvious.
Also, in the above example wa have BINGO & SNORK. One is a constant of the class, one a class level read only member variable. Which is which?
You are correct in that no two development teams in SAP use the same naming convention. I have observed before that some at SAP seem to have adopted the conventions mentioned in NOMEN_EST_OMEN. Again to repeat myself I like the idea of at least two people doing the same thing as opposed to ten thousand all doing something different.
That is enough for now, you probably think I am being very negative, but I stress again, all I am looking for is code to read like plain English as much as possible but not to the extent of making the reader have to guess about anything.
Cheersy Cheers
Paul
Regarding your SELECT-Statement, I do not think the mixture of mathematical symbols and set-operators 'IN' or string-operators 'LIKE' is a bad thing at all, there is no need to use EQ, GE, LE just for the sake of some curious form of uniformity. Your code is perfectly readable.
In some languages you can use unicode-operators for these operators too but this leads to some other form of voodoo'ism š
Regarding your Method, what about the following:
METHOD something.
DATA this TYPE string.
" we use prefixes for constants, altough you can argue about this too
this = zcl_class=>co_bingo.
" you can use natural ABAP syntax to make that attribute-access explicit (me->)
me->that = zcl_class=>snork.
ENDMETHOD.
I am waiting for the day I will get problems by the memory consumption of a local constant instead of a global one. An when I'll have, I will refactor it in 5 minutes š
Thank you very much for your comment, Paul, you're not being negative at all.
I use NE, GE etc. because I want to use EQ and be consistent. I want to use EQ because = is the assignment operator. Then SAP screw it up with READ.... KEY ... but what can you do?
For prefixes, I use
c_ for constants,
i_ for importing parameters,
e_ for exporting parameters,
x_ for changing parameters,
r_ for returning parameters,
me-> for class instance attributes.
classname=> for class static attributes.
_ty as suffix for types
That's it. No others. Internal tables will have names like
baryons with work areas like baryon
References to data will be ref_to_baryons
I also declare my data fairly close to just before I use it.
Like Paul, I'm a fan of making my code read as much as possible like plain English. Prefixes should indicate usage. Not type.
I also like to make my code read as much like English as possible... We still use prefixes to indicate the data type though.
is_ for importing structure,
it_ for importing table,
etc....
To me it still seems easier than trying to find a nice name to tell me its a table or whatever.
As far as instance attributes... I never use the me-> prefix... I find it just clutters things up.
At the end of the day... I think it comes down to personal + team preference. If you're all working with the same naming conventions then anything can work. It's when there are no conventions or 10 different conventions in the code that I get annoyed...
Hey Lcuas,
I'll have to second Matthew with "Prefixes should indicate usage. Not type."
It's impossible to write plain-english code, focusing on semantics and meaningful names, if you have to use technical type-prefixes.
Additionally, just regarding prefixes, I really think they should be used very sparely. Your brain/eye easily catches any noteworthy exceptions (like G_ if mostly no prefixes otherwise) while reading. This is really a big advantage.
Hi Lucas,
Any special reason for not using the self-reference (me->)? How do you differentiate between the static & instance attributes then?
BR,
Suhas
As I said, I just feel it clutters up the code for no good reason. If there are static attributes in my classes they are probably constants so they are named appropriately ie: co_
Other than that, unless it's a singleton with an instance attribute I really don't see any reason for static attributes. Therefore the distinction between static and instance attributes doesn't really matter.
I use it just occasionally to explicitly differentiate between attribute-access and local variables. But yes, generally Lucas' reasoning applies, it clutters up the code.
Good to hear there are others, too.
"I also declare my data fairly close to just before I use it."
Very good point, forgot about that. Anticipating the new ABAP 7.40 inline declarations and short LOCs, we also decided to declare the data right before using it.
I still prefer to:
1) prefix all variables, structures and internal tables, object and exception references in the perhaps mistaken belief that it permits to employ code completion features more efficiently, and
2) to identify scopes...
So its l_, ls_, lt_, lo_, lx_ for locals, g instead of l for global, m for members, s for statics, i, r, e, c for parameters.
The constants within the interfaces are prefixed using c too: again mainly for what 'I think is code completion convenience. There are some more preferences, quirky ones, like lr_ for range tables... I strongly agree about using me->.
Hi Jänis,
I don't understand how code completion would benefit from these prefixes?
In the sense that you quickly narrow down the set of possible choices?
I think it's even easier to identify scopes *without* those prefixes:
Cheers
Exactly, the extra coding in prefixing (categorising) helps narrow down the list of choices I'm trying to refer to (ideally to one) when using code completion, I feel. I prefer not to have to click here, click there (those small buttons) to narrow the lists...Let me try to illustrate... This code completion sugestion list is not yet good:
but, knowing it's a global object reference I'm looking for, just by typing another letter I get it (or them, in the few cases it would be needed):
It's even more helpful, I feel, when referring to stuff behind object references. This is next to useless:
yet this is almost good enough and by typing just anoher t letter I'd have a list of member internal tables:
Or within the local context of any size... this is useless, the local structure I'm looking for is not even in sight, if the keywords are not switched off:
but this is already good enough or even perfect, depending on the number of local structures:
Granted, inline declarations would obviate some of advantages here...
What is the point of <ls_tarifzundol>? It's a field symbol in a method. It must be local. Almost as bad as <fs_blahblah>... š
For "consistency" š Same convention as for locals - categorising the FS for variables (thus l_, so there is prefix of some kind...), the structures, and the tables, only enclosed in <>
<> declares it as a field symbol. And by definition they cannot be declared as attributes of a class. Simple knowledge of the ABAP language will help you avoid the l_ prefix in declaring field symbols.
That's what I'm after, using "simple knowledge of the ABAP language" to avoid many of those superfluous prefixes
On second thought - in the example I posted, <ls_..> is "wrong", because source lines for assignment come from input parameter it_... And the <is_..> <ls_..> <ms_..> and so on distinction (prefixing field symbols according to the intended source of assignment) is not redundant, I believe 😏
Code completion works as I understand it by looking at the first few letters of what you type and then suggesting the rest.
That is fine if you have four variables called
BINGO
FLEEGLE
DROOPER
SNORK
but what if they are called
LD_BINGO
LD_FLEEGLE
LD_DROOPER
LD_SNORK
In the fomer case if I type "SN" the code completion would know I meant snork, but if I typed in LD_ then it would not know which of the four to suggest.
Yes, but I cant possibly remember what name I gave what thing where (and considering the different "kinds" of "ratetypes" I have in my example, it's often back to list of things anyway...) - yet the prefixes I do know, always š
It seems very simple. There's the right way of doing things (my way), and then there's what everyone else does. I think everyone will agree with that - for their personal value of "my"!
It's either "my" way or the highway š
Exactly. If I do it your way, we'll both be doing it incorrectly.
5 Stars from my side š
B.t.w.: I will never understand why in prefix conventions it is, oh, so important to write something like mt_itab for an internal table that is a component of a class but no prefix is prescribed for an internal table that is a component of a structure. ls_struct-itab is OK? why not ls_struct-t_itab? readability?
It´s that lack of consequence that disturbs me most in most of the existing elaborated prefix naming conventions. In fact, I played around in creating a contradiction free prefix naming convention once, where each position of the prefix is clearly defined. I even succeeded, but that doesn´t mean that the programs became more readable ...
Print Workbench does have wa_ and t_ prefixing for structure and table components (that's all it works with) of complex generated types... š and I sometimes wish code completion could exclude simple fields from possible sugestions for operand positions requiring table type... One day maybe, on Hana..., or maybe it already does, on some release > 7.02? š
I just wish our tools (SE80, ADT) would provide a more complete syntax highlighting that would allow me to markup for example scope or type of variables. That way I could easily spot the odd wrong uses of Hungarian notation (which still seems very popular), where for example a global variable claims to be local, etc. Especially since we often have to wade through tons of spaghetti code and might work for clients with different standards. Of course even the syntax highlighting cannot make up for language ambiguities like TABLES parameters of function modules, which could be import, export or changing.
But even without the syntax highlighting we would have no issue, if there would be strict quality checks (always enforced) via ABAP Test Cockpit or Code Inspector, which offer lots of help to battle "bad" code and can enforce naming standards. But during crunch time delivering "a solution" seems often more important than providing a "clean solution".
And then I'd wish that more developers start adopting the cool new ABAP language features that allow far more concise coding (string templates, for comprehensions, etc.). But ABAP coding seems to be one of those areas, where one can easily survive with the coding style/constructs from a decade ago (strangely enough also by programmers, who started later than that) and nobody will complain.
Actually, the ADT can show you the selected variable's type, which is pretty cool.
ADT: display inferred type of DATA(foo) ?
Nice post! Thanks!
Especially dropping the unnecessary local prefixes. But i would miss the table-convention for table/entry processing. It's an easy and fast approach to get to your variable names without much thinking about it. Semantics can still be added if necessary and not clear by the particular context (of your method/loop/read). But the approach of "<subject>" for tables and "<subject>_entry" would be fine and looks nicer, but is not far different from the "t_<subject>", "s_<subject>" convention.
For your small method approach i am not sure if it's practical to measure it by loc. Maybe it's better to measure it by "statements". So the bloaty abap-syntax, empty lines and comments have no effect on this limiting value. I am not sure, but the sci can measure also statements?
Hi Christian, thank you for your reply š
Regarding
you are absolutely right.
Besides Horst Keller's reasoning that you don't want to have those technicalities in the name, I favor the reason not to use the t_/s_ prefixes simply to reserve the prefixes for emphasizing the ugly dirt (G_ ...). The brain/eye is very capable of detecting breaks in visual patterns like "oh, there is a prefix standing out, why's that?".
The LOC-counting is indeed a very stupid-metrics approach but we've heard some good arguments that seem to make it pretty effective:
So it's not about having a "good" or "fair" metric but a metric that is simply a threshold to the size of software-units to keep them manageable. In fact, our LOC-Tester is able to ignore comments or whitespaces but currently, it is running in the dumb LOCs from "start to end"-counting mode.
And yes, we implemented the SCI-Tester like CL_CI_TEST_METRIC_NOES does (using CL_CI_TEST_SCAN), so you actually get the scanned statements & tokens as a basis for counting LOCs.
Cheers,
Kai
Great post!
Automated tools like smartDevelop are boon to developers. It saves time, money and free up many resources.
I found this blog on automation. Upgrading your enterprise system through automated code remediation | SmartShift
Cheers,
AP
Yeehah!
Some one with common sense afterall! I've been ranting on about global variables for years. Global variables = a lazy programmer and a lousy program!!
I also abstract type definitions from the data dictionary for program use, and use the arbitrary convention of type-pools for 'Public' types and constants of a project and using an include for 'private' type declarations and constants.
This of course goes away when using objects.
I also use plurals of the line type when typing tables.... makes things a lot more readable later on.
Rich
The link to the Nomen est Omen-blog is semi-broken (it now links/redirects to Uwe's Profile, not the blog itselfe), here's aĀ direct link:
https://blogs.sap.com/2009/08/30/nomen-est-omen-abap-naming-conventions/