Source Code Layout
There have been several attempts to standardise the layout of source code. This is a good thing – if everyone used the same style we would spend less time trying to figure out what a slab of code actually does, free of layout inconsistencies and interpretations (and besides, everything would be clearly commented anyway, wouldn’t it).
The fact that there are several styles to choose from is an immediate oxymoron. Some styles were introduced because of limitations of the programming environment, such as writing code in 80×24 character screens ala DOS or Unix. Given such limited screen size, it would seem like a good idea to ensure the maximum amount of “code” is on-screen, rather than “wasting” lines with single brackets and the like.
An example in C of “The One True Brace Style”, a variant of K&R:
if (x < 0) {
printf("Negative");
negative(x);
} else {
printf("Positive");
positive(x);
}
According to Wikipedia, where this example comes from, both the Unix and Linux kernel are written in this style.
Now, I don’t have a problem with such styles per se, especially if they are born from visual limitations such as low resolution displays, but given that the majority of programmers these days, including myself, will be working with high-resolution monitors, such condensed styles seem visually anti-productive, as we shall explore.
It should be noted that other standards, such as K&R, Allman, KNF, and Whitesmith’s, provide a subtle range of more readable variations, though it is this programmer’s belief that they all still somehow miss a deeper level of visual presentation that can make code even more understandable and can be an actual aid to debugging.
What follows is a (somewhat terse) description of my own style of code layout that I’ve developed over the years. It is very visually based, which tends to be how my brain works. It’s also somewhat rooted in speed-reading techniques, where one develops the ability to take in large amounts of information without the struggle of reading every line of text.
It is also not without it’s own problems, as discussed at the end.
The standards mentioned above have generally been born out of the C world, however the following can be applied across a wide range of languages such as C++, PHP, Java, JavaScript, LUA, etc.
Indentation
Taking the C example above, we can re-write it like so:
if (x < 0)
{
printf("Negative");
negative(x);
}
else
{
printf("Positive");
positive(x);
}
As with Allman style, the curly braces are matched up with the control statements, which serves to provide a visual clue that there is going to be some kind of optional or repetitive action to be applied to the indented blocks of code.
We can see the two blocks are indented by the same amount and the ‘else’ statement is prominent between the two blocks, all clues as to the purpose of this code.
At a glance we can quickly summarise these lines like so:
if ( ... some condition ... )
{
... do some stuff ...
}
else
{
... do some other stuff ...
}
This trivial example introduces an important concept: if the control statements are obvious we can vertically scan the code quickly and get a feel for what it’s doing without needing to get bogged down in implementation details we don’t wish to concern ourselves with.
It is important then, to use braces even with single statements:
for( int x = 0 ; x < 10 ; x++ )
{
printf( "x = %d\n", x );
}
rather than
for( int x = 0 ; x < 10 ; x++ )
printf( "x = %d\n", x );
Whitespace
To further this concept, I tend to use whitespace very differently to any of the C standards. For example, I’d write the original example as:
if( x < 0 )
{
printf( "Negative" );
negative( x );
}
else
{
printf( "Positive" );
positive( x );
}
If the control statements are can be scanned vertically, the actual statements should be able to be scanned horizontally. By ensuring there is whitespace around every variable or value you make it easier on your eyes to pick out the parts of interest.
It is now also clearer that we are using the variable ‘x’ in the negative/positive function calls. By introducing whitespace we can see what values look visually alike rather then necessarily having to read them. If I had accidentally typed “negative( y );” instead, it would be much more obvious than if it had been all bunched up as in “negative(y);”.
You may also notice I removed the whitespace after the ‘if’ statement, for me this ties the horizontal bracketed condition to the ‘if’ rather than leaving it floating unconnected.
Changes in Language Style
The above guidelines work well for most general code but these days I’ve been encountering some challenges to my carefully honed model, especially within PHP and JavaScript where anonymous functions or large arrays of information need to be passed to other functions or methods.
Take something like this, from Symfony’s form system:
$this->setValidators(array(
'name' => new sfValidatorString(array('required' => false)),
'email' => new sfValidatorEmail(array(), array('invalid' => 'Email address is invalid.')),
'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))),
'message' => new sfValidatorString(array('min_length' => 4), array(
'required' => 'The message field is required',
'min_length' => 'The message "%value%" is too short. It must be of %min_length% characters at least.',
)),
));
If we are to apply a similar layout as described above, it will end up as something like this monster:
$this->setValidators
(
array
(
'name' => new sfValidatorString
(
array
(
'required' => false
)
),
'email' => new sfValidatorEmail
(
array
(
),
array
(
'invalid' => 'Email address is invalid.'
)
),
'subject' => new sfValidatorChoice
(
array
(
'choices' => array_keys( self::$subjects )
)
),
'message' => new sfValidatorString
(
array
(
'min_length' => 4
),
array
(
'required' => 'The message field is required',
'min_length' => 'The message "%value%" is too short. It must be of %min_length% characters at least.',
)
),
)
);
This introduces are mildly unpleasant side-effect where functions, constructors, and arrays are being laid out like control statements. Also, nine lines of code now take up almost a whole page! Now I’ve come full circle, back to needing some hybrid condensed version to adjust the code to layout on-screen ratio.
Oh, what to do… Perhaps a bigger monitor?