Beyond pretty printer – legible code in times of ABAP 740+
Pretty printer is very useful, but in some cases, you have to be a “Pretty coder” yourself.
Especially with ABAP 740, where all those expressions came up and finally made us feel like real programmers – as we now could do things like
data(ls_result) = new lcl_data_processor( new lcl_data_provider( p_matnr ) )->do_something_important( iv_simulation = abap_true ).
just like all the others.
The ABAP statements are getting longer these days, so I asked myself how to distribute them into several lines and keep the legibility. I started with something like
if line_exists( lt_process[ orderid = ls_queue-orderid
activity = ls_queue-activity ] ).
But when it comes to real deeply nested expressions, this would lead to enormous line sizes. What I am doing nowadays, is more like this:
rt_res = value #(
for s_oper in lt_operations where ( sub_activity = space )
( value #(
let ltext = actvt_longtext_read( s_oper ) in
act_end_date = s_oper-act_end_date
act_end_time = s_oper-act_end_time
act_start_date = reduce d(
init d = s_oper-act_start_date
for s_sub in it_sub_oper where (
i.e. increase indentation by bracket level. When closing the brackets, I just do
then cond #(
when s_subd-isdd < d
then s_subd-isdd
else d )
else d ) ) )
that is closing everything in one line.
Still I’m not totally satisfied with my approach, especially with the closing of bracket levels. But wasting a line for each closing bracket seems ugly to me.
What is your approach in coding very long ABAP statements?
Hello Jörg,
you might want to check Scheme's guidelines.
regards,
JNN
Excellent link!
Excellent link, indeed! Thanks Jacques Nomssi Nzali !
An excellent topic. But I would like to add this predates 7.4, but the new syntax has just complicated it.
My view is that there is a degree of personal taste and style. I tend to make a little effort to format code nicely, with future readers in mind.
Too much horizontal information decreases legibility, as does too much vertical. So it depends a little on the content.
I try not to make lines too long, as people (myself included) should also be able to read it on a laptop or in the debugger. So 'hanging vertical' arrangements are OK if the line isn't too long, otherwise I start to wrap it. The important thing is consistency - putting all grouped bits together.
Note that I'm putting two parameters on the same line in the last example. Usually each parameter gets it's own line, but here the tabular format of the entire name-value dataset is more sensible.
All in all it's content-driven. Consider simple SQL statements, just for fun here are two styles applied to the wrong type of statements:
This format makes sense to me. The last statement is easily readable as well as easily copy-pasted if someone needs to add another value.
I'm glad to see at least someone understands the value of readability. Unfortunately, some of the 7.4 statements seem to be a "how much can I stuff into this one command" contests. It looks much better when formatted like in these examples. It's like a well edited book. 🙂
Nice blog, Jörg Krause !
...and the reason my comment ended rather suddenly is because I posted by accident and couldn't edit it. One of the many long-standing bugs on this "new" platform.
I was going to write something along the lines of folks that cram a huge long SQL statement into one line vs others that write "vertical SQL" for even the simplest thing. I find this kind of thing painful:
Well, I'm actually in favor of writing selects like that regardless of how complex they are (or get).
I do put more than one field into a line of the field list though - how many depends on the number of fields all told and how long the names are. This is how it might look:
To me, having the same format for each select in a program improves readability and I find it more painful if each select has a different look and feel. ?
I also tend to do "vertical" sql statements - just to be able to easily add things like fields or conditions afterwards.
I see that you align the keywords in your select in order to align the following denominators. This may be an optical advantage, but to me it seems to be an obstacle in fluently typing in the code.
My approach here is:
note that I use the new SQL syntax here. Especially to have one line for each field of the field list makes it easier to add new fields afterwards. Apart of that, it lets you use the block select function of the editor to grab all fields, which comes handy if you later want to create an according type for the result.
I think you're missing my point. Your example is sensible and close to the way I'd write it.
We read from left to right, so this is the easiest to read if the logic is simple - e.g. my example of picking a single value from a table, or checking existence or counting. There's no need to split this over three lines:
It's perfectly understandable as is. Contrast with:
Writing it as a list of clauses decreases readability in this case because we have to scan left to right and up and down. Typically I find myself reading the second version twice to make sure I understood it.
So my original point is that it's about balance. When the statements get more complex, then ease of comprehension is more important than ease of reading. Horizontal makes for more fluid reading, vertical provides more structure.
I understand both of you Bärbel Winkler and Mike Pokraka and I often switch between both variants. When is a statement short enough to put it in one line and when should I split it into several lines? It depends on many things - at least on the weather outside... 😉
One word about "reading": you mostly do not read everything. You fly over the code. Therefore the column based format is much better, because your eyes can catch the content easier. Even if the lines are not that long.
Mostly I try to format the code by respecting best copy and paste and inserting and deleting conditions. That means: If there is something in the command or command flow that might become obsolete or if there must be inserted something: What is the best format w/o touching the adjacent lines?
Therefore I mostly do not use colons like
Instead I always use:
This makes it easy to decomment unused variables or cut variables when refactoring the function. It also makes it easier to group variables to blocks using CTRL-ALT-UP/ DOWN:
The same with SELECT fields FROM or VALUE
Overall: Beautfying all the complex new 740+ commands is really a challenge... 🙂
On the other hand, if you use colons for multiple data/type declaration, pretty printer helps you aligning the statements:
Since I am working often with block selection of variables, this comes handy to me.
Not sure, if I'm really missing your point, Mike! I guess it just comes down to slightly different points of view with my preference being a similar format for each select statement in a program. I'm actually quite happy that ABAP is flexible enough to not really insist on a specific way/sequence to write statements like this - otherwise it would just be one more thing to memorise and stick to (and there are more than enough of those already).
I agree. I write exactly like in your example above, although if it's just one field I might write SELECT ... INTO ... and then the rest on the next lines.
This seems more of a personal preference / style thing. I wouldn't hold back a code review if I saw Mike's version either. It's just a habit for me to write on separate lines. Besides, simple statement today, complex tomorrow. 🙂
When it comes to SELECT, the most irritating thing though is ABAP's very strong preference in the placement of spaces and parenthesis. And if you do it wrong, you don't get an intelligent error message like "hey, I think you forgot a space here" but something like "I have no idea what these fields are". At least in 7.3, maybe this got improved in later versions.
Haha, I thought you had somehow implemented a screenshot from some 3rd-Party site, which was then blocked by my uMatrix-Opera AddOn - great to learn the explanaiton is much simpler!
Thanks for this blog post, Jörg!
As a veritable newbie when it comes to ABAP OO, I very often have a hard time deciphering what long statements actually produce as a result. I even tend to "space out" much like I do when confronted with mathematical or scientific notations and formulas. So, something I really appreciate in addtion to thoughtful formatting is a clarifying comment preceeding such a statement.
I'm also a fan of a strategically placed empty line preceeding and following (blocks of) statements.
My solution? Don't do it! 🙂
Just one more thing 🙂
What do you think about BIG indentations like the one in Mike Pokraka 's comment:
In my development team, this is quite popular whilst I do not like it. Often when I'm working on a laptop and the window is narrow, parts of the code go beyond the right window border.
Or think having to rename something
Or even when an expression comes in charge
Do you get the point? I do remain on one line if there's only one element inside the brackets and the line is not too long
I did say I do it variably. Yes, changeability is a small sacrifice and I am careful about nesting hanging indents. Generally I keep to a maximum of 80-100 character lines, only going longer where it's relevant.
To use your example, find this is slightly less readable:
So personally I’d write it in mixed mode:
But all of this is hardly anything new, consider the following fine example of classic ABAP from function module SWW_WI_START:
We have the same issues of lining up after renaming.
And then there are people who write:
This one goes against my sense of aesthetics.
Well, I guess legibilty is a matter of opinion. I would prefer
in your example. Again – a matter of personal preferences.
By the way, there are two situations when I use those “tabular” indentations:
Why? Because the pretty printer has this pattern of formatting, so I adapted it. Otherwise I would have to adjust the coding after each pretty print…
I think it has practical sides to it too. If I’m skimming through at a page per second that just looks like a badly indented was-changed-but-not-pretty-printed method call with 5 parameters at first glance. It takes a second slower look to spot the parentheses. That’s why I prefer bigger offsets. But all variants are easily understood so it is still largely a matter of preference.
Actually you’ll find that eclipse will indent depending on how you arrange it. If you put the METHODS…. IMPORTING on the same line, it’ll do this:
And a pet peeve is that SE80 will then go and reshuffle whatever Eclipse does and also prefix everything with !
Oh my, those exclamation marks - how I hate the formatting that se24 does in form based mode.
However - this is not the pretty printer but the code generation of se24 form based mode. Since I am using (almost) always the source based class builder, my public classes do not have this ugly look - and I am using pretty prnter in there.
Of course I must be careful because sometimes the form based builder is is being called whithout my intention ("Edit" button after syntax check for example)
Not only that, but SE80/SE24 also re-orders methods. Annoying.
Thanks for the wonderful blog, but the horrible thing is even in S/4 with ABAP 7.5 I see many developers writing forms and crap code and the QA passing it. What can SAP do?
Nothing or may be now just kill the backward compatibility in any custom code. Can it work I don't know but some people and some teams never want to learn 🙂