# Code Readability for "Higher" Level Languages

Homework Helper
There really is no specific guideline for this. Personally, I like to write my code as compact as I can, but is there really a problem with this? Having those small complicated statements can make code hard to read, but is that not up to the developer's/reader's level of skill?

For example, the following is a piece of code written in java (A language I'm sure most programmers are familiar with, so I'll use it for this example). It is written inside a Seat class where there is a private field called 'booked' of type boolean. It should be fairly clear what this code segment accomplishes:

Code:
  /**
* If this seat is available, books it and returns true.
* If the seat is not available, returns false.
*
* @return boolean: True if the seat was successfully booked, false otherwise.
*/
public boolean book(){
if(!booked){
booked = true;
return true;
}
return false;
}
Below is a piece of code which accomplishes exactly the same thing. Although you will notice the syntax is significantly different:

Code:
  /**
* If this seat is available, books it and returns true.
* If the seat is not available, returns false.
*
* @return boolean: True if the seat was successfully booked, false otherwise.
*/
public boolean book(){
return !booked ? booked = !booked : false;
}
Many will claim the second piece of code is hard to read, and they would prefer the first version.

Is there really a disadvantage to writing code like in the second code block? I think it might be coder's apathy if anything.

More importantly, are there actual advantages to writing code so compactly? Does it influence the run-time in any fashion? Does it have other benefits?

When is code readability actually a factor? If you are working with software professionals, I'm sure they would be able to read both versions anyway.

What are your opinions?

## Answers and Replies

Related Programming and Computer Science News on Phys.org
Mark44
Mentor
There really is no specific guideline for this.
An excellent resource is "Code Complete" by Steve McConnell.
Zondrina said:
Personally, I like to write my code as compact as I can, but is there really a problem with this?
Absolutely there is. First, why do you think there is an advantage in writing "compact" code? The "compact" that you refer to is the density of the source code, which is only loosely related to how compact the object code/executable is. Second, writing compact (or terse) code obscures the meaning, which makes it much more difficult for a programming, even yourself after several months, to ascertain what the code is doing.
Zondrina said:
Having those small complicated statements can make code hard to read, but is that not up to the developer's/reader's level of skill?
A given piece of code can live on for many years after it is initially written (see Software Life-cycle). The original developer is often not the same person who wrote the code. Even worse, the original developer very likely was too clever by half in making the code inscrutable, which caused bugs to appear. By writing dense, inscrutable code, the "clever" programmer is making the maintenance programmer's job much more difficult, possibly causing additional bugs to appear, due to the maintenance programmer's changes to fix the original programmer's bugs.
Zondrina said:
For example, the following is a piece of code written in java (A language I'm sure most programmers are familiar with, so I'll use it for this example). It is written inside a Seat class where there is a private field called 'booked' of type boolean. It should be fairly clear what this code segment accomplishes:

Code:
  /**
* If this seat is available, books it and returns true.
* If the seat is not available, returns false.
*
* @return boolean: True if the seat was successfully booked, false otherwise.
*/
public boolean book(){
if(!booked){
booked = true;
return true;
}
return false;
}
Below is a piece of code which accomplishes exactly the same thing. Although you will notice the syntax is significantly different:

Code:
  /**
* If this seat is available, books it and returns true.
* If the seat is not available, returns false.
*
* @return boolean: True if the seat was successfully booked, false otherwise.
*/
public boolean book(){
return !booked ? booked = !booked : !booked;
}
Slightly different? I don't think so. The code in the first example is clear. You would have to work extra hard to make the code in the second example less clear.
Zondrina said:
Many will claim the second piece of code is hard to read, and they would prefer the first version.

Is there really a disadvantage to writing code like in the second code block? I think it might be coder's apathy if anything.

More importantly, are there actual advantages to writing code so compactly?
Most of the time, nol
Zondrina said:
Does it influence the run-time in any fashion?
It's quite possible that the compiler will produce the same object code in both cases.
Zondrina said:
Does it have other benefits?

When is code readability actually a factor?
Most, if not all of the time.
Zondrina said:
If you are working with software professionals, I'm sure they would be able to read both versions anyway.
There is not a single level of software developers. One of the most important attributes of a software developer is to write code that can be easily understood by humans. Virtually all code that is produced by humans has faults in it, and writing "clever" code makes it more difficult for others to find and fix those bugs.
Zondrina said:
What are your opinions?

seastryder, jim mcnamara and Merlin3189
Homework Helper
You would have to work extra hard to make the code in the second example less clear.
Never too hard.

maintenance programmer's job much more difficult
I feel as if coding classes are trying to teach you to be maintenance programmers. It's almost as if the clever solution is actually wrong.

Mark44
Mentor
I feel as if coding classes are trying to teach you to be maintenance programmers. It's almost as if the clever solution is actually wrong.
In some respects, an overly clever solution is wrong. To clarify what I mean, if a section of terse, impenetrable code makes it difficult to make changes to that code, and increases the probability of more bugs, this could convince customers to look for a different software provider.

If you don't have the McConnell book I cited, and you have aspirations to write code, get it.

Merlin3189
Homework Helper
Gold Member
Yes. No. No. No. Whenever code is read. Always write for clarity and avoidance of possible errors, except when replying to questions like this.

Merlin3189
Homework Helper
Gold Member
I feel as if coding classes are trying to teach you to be maintenance programmers. It's almost as if the clever solution is actually wrong.
What makes obscure code "clever"? Sometimes clever code is obscure, but turbidity or obscurity does not make it clever.

In your example there is a simple straightforward way of doing the job. What is clever about rewriting it in a less obvious way? As Mark said, it will probably result in the same object code.

I think you have to ask yourself, why you are writing the code. Are you trying to show how clever you are, or are you trying to write code that works? If the former, your clever code may be better, but if the latter, then the original code is better by far.

As for maintenance programming, try it sometime if you think you're good enough. Anyone can write their own code, but it is not so easy to modify someone else's.

FactChecker
Gold Member
One place where the compact form is better is where there are several similar, simple lines that can be put one after the other. Then it is easier to see the similarities and the differences from one line to the next. Your examples should not disturb anyone, but some people go crazy with conditions nested within conditions, within conditions. You would be surprised. I think that many coding standards are there to stop people like that.

Regarding speed: An optimizing compiler will probably create the same series of operations from both types of code. No speed difference.

Last edited:
D H
Staff Emeritus
Is there really a disadvantage to writing code like in the second code block?
Considering that the programmer who is assigned to maintain your code may well be a homicidal maniac who knows where you live (those are not my words), yes, there really is a disadvantage to writing code like you wrote in the second code block.

In a more serious nature, you certainly aren't going to write booking software like either of the two code blocks. What if users X and Y try to simultaneously book the same seat? I've been on flights where my boarding pass and another person's boarding pass had us sitting in the same seat. The mess that ensues can indeed turn one into a homicidal maniac hellbent on finding where the stupid programmer for that double booking lives.

In real life, you may well need to do a lot more than using the ternary operator to perform tricky little bit of logic. Don't be tricky. That other logic (which is essential) is complex enough to give a maintenance programmer headaches. Don't add non-essential headaches to the essential headaches that cannot be avoided.

More importantly, are there actual advantages to writing code so compactly? Does it influence the run-time in any fashion? Does it have other benefits?
Tricky code is not only hard for another human to understand, it's also hard for a compiler to understand. Your tricky tricks may well be suboptimal as far as performance is concerned.

I fully understand the appeal of the ternary operator. Deep in the core of me, there lurks an FP (functional programming) mindset. The ternary operator appeals to that mindset. I also know that most people (and that includes some otherwise very good programmers) are deeply confused with overly complex boolean logic (guilty), the ternary operator (guilty again), the comma operator (guilty yet again), and extended regular expressions that are over 100 lines long (also guilty!).

I wrote the programming standards for multiple projects at NASA. In almost all of them, I authored some 'anti-DH' rules that forbade the use of the ternary operator and comma operator. When asked why, I had plenty of code golfing code to show them (some written by me) that demonstrated why that rule was a good idea.

STEMucator and FactChecker
FactChecker
Gold Member
In real life, you may well need to do a lot more than using the ternary operator to perform tricky little bit of logic. Don't be tricky. That other logic (which is essential) is complex enough to give a maintenance programmer headaches. Don't add non-essential headaches to the essential headaches that cannot be avoided.
Agree. Baby steps are best. It is better to divide a complicated expression into smaller logical parts and steps. It does not slow the computer down. It always seems to be the part that you trusted the most that has a bug. And it is always easier to spot a bug when it stands alone in a simple operation. If a bug is buried in a complicated expression, good luck.

nsaspook
DH, Bravo... When I see code like this it makes me think someone wants to make their code unreadable for job security.

Tricks are for kids.

Mark44
Mentor
Here's an entry from the International Obfuscated C Code Contest, from the 2012 contest.
C:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int u,z,q[0400],O[0x101],o[0401],I[257],w[258][0403],W[0x100],Z[0x103],c[0403],k
,i,j,n,l,p,m;const char*J[0416],*M[0400];FILE*K[280],*s[0x102];void f(char*n,int
a){char*e=n;while(*e!='\0'){if(tolower((int)*e)!=*e)fputc(040,stderr);fputc((*e)
-a,stderr);e+=1;}(void)fputc('\n',stderr);}int y(int a,int b);int t(int i,int j)
{int k=i&j,l=i^j,n,m=1;for(n=1;k>=n;n<<=1)if(k&n)m=y(m,1<<n|1<<(n-1));return m>1
?y(m,1<<l):1<<l;}inty(inta,intb){intn,i=0x0,j;if((n=w[a][b]))returnn;for(;a
>>i;++i)for(j=0x0;b>>j;j++)if(((a>>i)&1)&&((b>>j)&1))n^=t(i,j);return w[a][b]=w[
b][a]=n;}void a(void){for(i=0;i<z;i++){n=0;if(!i[I]){for(j=0;j<u;++j)if(i[O]==q[
j])n=Z[j];}else for(j=0;j<u;j++)n^=w[Z[j]][w[I[i]][W[w[o[j]][O[i]^q[j]]]]];c[i]=
n;}}void X(int v,int u){char*y=0;v-=1;switch(v){case(0x2):y="HckngfVqQrgpKprwv"
"Hkng"; BC(4):y="JempihXsStirMrtyxJmpi"; BC(0):y="PointValueTooLarge"; BC 0x1:y=
"EvqmjdbufJoqvuQpjou";BC(6):y="TuOtv{zLorky";BC(3):y="WrrPdq|RxwsxwSrlqwv";BC(5)
:y="GfiFwlzrjsyX~syf}"; BC(07):y="UvV|{w|{Mpslz";}if(u)exit(0); f(y,v);exit(1);}
int main(intt,constchar*T[]){for(i=00;i<0x100;++i)for(j=0;j<=i;++j)if(1==y(i,j
))W[i]=j,W[j]=i;for(k=0x1;k<t;k++){p=0;for(l=0;(T[k][l]>=toupper('0'))&&(T[k][l]
<=tolower('9'));l++){p=p*10+(T[k][l]-'0');if(p>=256)X(1,0);}if(T[k][l]=='-'){for
(m=0;m<u;m++)if(q[m]==p)X(2,0);q[u]=p;J[u]=T[k]+l+1;K[u]=fopen(J[u],"r");if(!u[K
])X(3,0);u++;}elseif(T[k][l]=='+'){if(z>=256)X(4,0); O[z]=p;M[z]=T[k]+l+1;s[z]=
fopen(M[z],"w");if(!s[z])X(5,0);z++;}else X(6,0);}if(!(u!=0))X(7,0);if(!(z!= 0))
X(8,0);for(i=0;i<u;i++){n=1;for(j=0;j<u;j+=1)if(j!=i)n=w[n][q[i]^q[j]];o[i]=n;}
for(i=0;i<z;i++){n=1;for(j=0;j<u;j++)n=w[n][O[i]^q[j]];I[i]=n;}while(!(0)){for(k
=0;k<u;k++){intn;n=getc(K[k]);if(n==EOF)X(42,1);Z[k]=n;}a();for(k=0;k<z;k++)(
void)putc(c[k],s[k]);}X(11,1);}

STEMucator and Merlin3189
D H
Staff Emeritus
Here's an entry from the International Obfuscated C Code Contest, from the 2012 contest.
That code is broken. Here's a link to the correct version: http://www.ioccc.org/2012/grothe/grothe.c.

Note that you have to compile with '-DBC=break;case' .

Here's another IOCCC entry, from 2011. It won "best self documenting program".
C:
#define clear 1;if(c>=11){c=0;sscanf(_,"%lf%c",&r,&c);while(*++_-c);}\
else if(argc>=4&&!main(4-(*_++=='('),argv))_++;g:c+=
#define puts(d,e) return 0;}{double a;int b;char c=(argc<4?d)&15;\
b=(*_%__LINE__+7)%9*(3*e>>c&1);c+=
#define I(d) (r);if(argc<4&&*#d==*_){a=r;r=usage?r*a:r+a;goto g;}c=c
#define return if(argc==2)printf("%f\n",r);return argc>=4+
#define usage main(4-__LINE__/26,argv)
#define calculator *_*(int)
#define l (r);r=--b?r:
#define _ argv[1]
#define x

double r;
int main(int argc,char** argv){
if(argc<2){
puts(
usage: calculator 11/26+222/31
+~~~~~~~~~~~~~~~~~~~~~~~~calculator-\
!                          7.584,367 )
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
! clear ! 0 ||l   -x  l   tan  I (/) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
! 1 | 2 | 3 ||l  1/x  l   cos  I (*) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
! 4 | 5 | 6 ||l  exp  l  sqrt  I (+) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
! 7 | 8 | 9 ||l  sin  l   log  I (-) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(0
);
}
return 0;
}

Even python is obfuscatable. Runs on a command line interpreter with a unix-like OS. Want a prettier picture? Just embiggen your terminal window.
Python:
from os import popen
from functools import reduce
t=['pu'.join(['t']*2)]+[x.join(list(' s'))for x in('col','line')];print((lambda
Ru,Ro,Iu,Io,IM,Sx,Sy: reduce (lambda x,y:x+y,map(lambda y,Iu=Iu,Io=Io,Ru=Ru,Ro=
Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,Sx=Sx,Sy=Sy:reduce(lambda x,y
: x+y,map (lambda x,xc=Ru, yc=yc,Ru =Ru,Ro=Ro,i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=
lambda xc,yc,x,y,k,f:(k<=0)or(x*x+y*y>=4.0)or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k
-1,f):f(xc,yc,x,y,k,f):chr(64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(
popen(t[0]+t[2]).read())))

I feel code 1 is more redable. Any one can understand from new starter to experienced person. And as some mentioned compiler will produce same byte code for both.
There is another aspect to this. We are talking about private data member. Private data member should always have geter and /or setter with required visibility.Once you have setter, it must be used to set the value of private data member. If you follow this principle, code 1 is more suitable and readable.
So my vote goes to Code #1.
Remember: Code need not be compact but must be easy to understand, to everyone.

The compiler will most likely produce the same machine code for both sets of code. The only difference between using an if statement and a ternary operator is that you can give the compiler some hints:

Code:
if (__LIKELY__(x == 1)){
//Most common case
} else {
//Other case
}
Usually the only time you care about things like that are supercomputers and kernel code.

nsaspook
Usually the only time you care about things like that are supercomputers and kernel code.
There are coding standards even in kernel code.
Linux:
https://www.kernel.org/doc/Documentation/CodingStyle
Don't put multiple assignments on a single line either. Kernel coding style
is super simple. Avoid tricky expressions.

Last edited:
nsaspook
Yes, most projects do.
http://stackoverflow.com/questions/...the-linux-kernel-how-do-they-work-whats-their

A detailed explanation of the difference is here on page 57: http://www.akkadia.org/drepper/cpumemory.pdf
I've found it can make a huge difference in very specific circumstance.
Optimizing branching and memory access is complex (a necessary requirement for good kernel code) , writing it with tricky functions just makes it complicated.
something that is complex can be broken down into simple parts, without being simple itself. This allows mostly smooth functioning with solvable problems.

"complicated" is indicative of something that is problematic, convoluted, difficult and inconsistent.
https://www.englishforums.com/English/ComplexComplicated/dqrvk/post.htm

Homework Helper
Yes, most projects do.
http://stackoverflow.com/questions/...the-linux-kernel-how-do-they-work-whats-their

A detailed explanation of the difference is here on page 57: http://www.akkadia.org/drepper/cpumemory.pdf
I've found it can make a huge difference in very specific circumstance.
That link to the CPU memory article was quite interesting, thank you for sharing. Page 57 was quite insightful on its own:

If the condition is frequently false, the execution is not linear. There is a big chunk of unused code in the middle which not only pollutes the L1i due to prefetch-ing, it also can cause problems with branch prediction. If the branch prediction is wrong the conditional expression can be very inefficient.
I wonder why they simply don't depreciate things if they don't want people using them. Although the ternary operator does have some usage in deciding what to print.

rcgldr
Homework Helper
What is considered to be a high level language these days? In the past, C / C++ were considered as medium level languages.

One example of a high level language, but with difficult readability is APL, where it's common to write compact code, and the language features single greek letter operators, and strict rules for order of evaluation. Sometimes jokingly called a write only language since no one can read it. Wiki link:

http://en.wikipedia.org/wiki/APL_(programming_language)

Take a look at the game of life example. Here's a video explaining an alternate version:

Last edited:
Mark44
Mentor
newjerseyrunner said:
A detailed explanation of the difference is here on page 57: http://www.akkadia.org/drepper/cpumemory.pdf
I've found it can make a huge difference in very specific circumstance.
Zondrina said:
That link to the CPU memory article was quite interesting, thank you for sharing. Page 57 was quite insightful on its own:

If the condition is frequently false, the execution is not linear. There is a big chunk of unused code in the middle which not only pollutes the L1i due to prefetch-ing, it also can cause problems with branch prediction. If the branch prediction is wrong the conditional expression can be very inefficient.
I wonder why they simply don't depreciate things if they don't want people using them. Although the ternary operator does have some usage in deciding what to print.
What you quoted isn't about the ternary operator or branches (if () else ..). Ulrich Drepper is not saying that these things are bad. What he is saying is that how they are used can lead to inefficient use of cache memory. In particular, a block of code like this:
C:
if (<condition>) {
<do something>
}
else {
<do something else>
}
If <condition> is usually false, it fouls up the branch prediction and the CPU instruction pipelines aren't valid, and have to be refilled. That's what he's talking about with the execution being non-linear.

nsaspook
D H
Staff Emeritus
Optimizing branching and memory access is complex (a necessary requirement for good kernel code) , writing it with tricky functions just makes it complicated.
<begin tongue-in-cheek>
As everyone knows, the standard algorithm for determining whether a year y is a leap year is
C:
bool is_leap (int y) {
if (y%25 == 0)
return y%16 == 0;
else
return y%4 == 0;
}
Thanks to the bang (!) and ternary operators, this becomes the one-liner via
C:
bool is_leap (int y) { return !(y%(y%25?4:16)); }
There's still a problem here with regard to highly optimized code. Just as the if version slows down the computer thanks to that decision point, so does the ternary operator. It's just hiding the decision. A decision-free one liner that takes just a few more characters than the terse ternary version is
C:
bool is_leap (int y) { return !(y%(4<<2*!(y%25))); }
<end tongue-in-cheek>

The standard implementation of is_leap is of course
C:
bool is_leap (int y) { return (y%4 == 0) && ((y%100 != 0) || (y%400 == 0)); }
Even though that standard implementation doesn't have a single if statement or a single ternary operator, there are at least two, and perhaps as many as five, decision points hiding in that standard algorithm. Kernel and cuda programmers go out of their way to convert those decision-full algorithms to decision-free algorithms.

The standard algorithm is the preferred implementation for everyone but a kernel or cuda programmer.

STEMucator
You probably need to know a little more about how a computer reads a program to fully understand why branch prediction matters so much.

When the CPU is executing a command, logic says that it's grabbing one command, running it, grabbing the next, running it... In reality, that couldn't be further from the truth.

When the CPU is executing a command, it's running it, it's also running the next command... probably the next handful all at the same time. It won't actually complete them until the previous one is done, because it may depend on the results of the previous command. So when it comes to an if, while it's executing the if, it's already also executing whats inside of it. This is called a pipeline. If the if statement fails, all of what the CPU has already done is scrapped and program execution is moved somewhere else. This is wasteful. It also doesn't load one command at a time, it loads large numbers of them in a block. 99.9% of the time, the next command to run, is the one right after it, so it makes sense to load many commands into cache as possible. If the execution of an if fails, the else code, is probably not located in the same block and a completely new block of code has to be loaded into the cache from the RAM.

Homework Helper
What you quoted isn't about the ternary operator or branches (if () else ..). Ulrich Drepper is not saying that these things are bad. What he is saying is that how they are used can lead to inefficient use of cache memory. In particular, a block of code like this:
C:
if (<condition>) {
<do something>
}
else {
<do something else>
}
If <condition> is usually false, it fouls up the branch prediction and the CPU instruction pipelines aren't valid, and have to be refilled. That's what he's talking about with the execution being non-linear.
I know, this thread has jumped to an entirely different topic concerning branch execution. I was just highlighting an interesting point I saw in the PDF.

I never even knew branch execution was so far-reaching till I read that.

Also, I was just making a comment about the ternary operator itself, and how it doesn't seem to serve too much purpose.