Structure of source code

If you take a look at figure 1 below, you will most likely see nothing but a shapeless set of ink blots. Well, it is a shapeless set of ink blots after all, so I would be surprised if you see something else in there.


Figure 1.

If you look at figure 2 instead, the picture in your mind changes dramatically, even if the picture contains exactly the same elements as figure 1. This time you will have no problem telling that elements of figures 2a and 2b belong together, and also that figure 2b very closely resembles a square even if several parts are missing.


Figure2a and 2b.

So, that's all good but... how does it apply to programming?

The answer is that with the proper structure you can make code easier to read and understand. On the contrary, if your goal is to write harder and unmaintanable code then by all means start with the right foot by giving it a bad structure!

In fact, structure and organization is one of the most important attributes of source code. When you look at a source code for the first time it's not the content you notice first, but rather its shape. Sometimes, this is just enough to give you bad feelings about the hours to come: a bug must be fixed quickly, and yet the code seems to have no head or tail. Things are very different if the code is clean and well organized: yes, there might be a bug in some place over there, but it doesn't feel so impossible to find it!

The idea behind structuring is very simple: elements that are logically related should also be visually related. The most essential tools for shaping the code are grouping and indentation.

Grouping means that related elements are put close together. As shown if figure 2a, this has an immediate impact on how these elements are perceived and this is true for all sorts of visual communication. Even plain text is usually divided at least in paragraphs. It is difficult to give out absolute rules for source code. For example, it is good practice to insert a blank line to separate unrelated pieces of code, but please do use blank lines in other situations if you see fit. Comments are often useful and at times a special line all made of characters such as '-' or '*' has its place too. It is not very useful to try and enumerate all possible cases but stopping for a few seconds to ponder a new situation as it occurs in practice, that's time well spent.

Indentation is less intuitive than grouping but also more powerful, as it can express the "depends upon" or "contained by" relationship that is so important for structured programming. Indentation also happens to be one of the hot topics for programmers, who are known to be able to spend countless hours and discussing whether one style is better than another. Each time they are started in public forums, discussions on this topic quickly degenerate in holy wars in which participants flame one another, so no agreement on a good indentation style exists or is likely to exist in the near future. Fortunately we're not going after a particular style, so you can relax at least for the next few paragraphs. Still, it is useful to examine the subject briefly so you can choose for yourself, as not all indentation styles are equally good.

As shown earlier in this chapter, there are some visual arrangements that make more sense to the eye than others. Since the compiler cannot care less, it is possible to write a perfectly good program without indenting at all. In fact, C programmers used to run the so called obfuscated source code contests where the first prize goes to the less readable and most confusing code. While the C language allows for a variety of methods to be employed, the lack of a coherent indentation is still one of the most effective tricks in the programmer's bag. If that seems an exaggerated example, here is a function that found its way almost into production code (the extra blank lines are from the original):

void run_n_write_query(Query_Id query_id, char *query_name, char* host_name, 
               char* file_name, char* del, short header_on)
{


    DATABASE_val_row         row ={0};
    
    SysProperties                       _sysp ={0};
    

    list_t*                             lh = list_create();

    		    
	write_query_to_local_file(query_id, query_name,
                              file_name, del, 
                              header_on,host_name);

 			
}

When this function is properly reformatted and indented, it is much easier to see that it is simply a proxy for another function. It can then be deleted without remorse (and it was).

Unless such obvious cases however, evaluating and choosing an indentation style may be more difficult. Here is a style that has been used in most of the GNU code but has found little favor elsewhere:

    for( int i=0; i<10; i++ )   //    #########################
      {                         //      #
        int a = foo();          //        ##############
        int b;                  //        ######
                                //    
        if( a > 0 )             //        ###########
          {                     //          #
            b = 1;              //            ######
          }                     //          #
        else                    //        ####
          {                     //          #
            b = 2;              //            ######
          }                     //          #
      }                         //      #

The principal issue many have with this style is that placing brackets midway between two logical indentation steps doesn't serve any practical purpose and in fact somewhat confuses the separation between the two indent levels, as shown in the right where letters and spaces have been replaced by '#' to evidentiate the style structure.

A style that has found a lot more favor is the following BSD or Allman style:

    for( int i=0; i<10; i++ )   //    #########################
    {                           //    #
        int a = foo();          //        ##############
        int b;                  //        ######
                                //    
        if( a > 0 )             //        ###########
        {                       //        #
            b = 1;              //            ######
        }                       //        #
        else                    //        ####
        {                       //        #
            b = 2;              //            ######
        }                       //        #
    }                           //    #

where the indentation levels are clearly shown.

The so called K&R style has found a new popularity when Java adopted it as the preferred style:

    for( int i=0; i<10; i++ ) { //    ###########################
        int a = foo();          //        ##############
        int b;                  //        ######
                                //    
        if( a > 0 ) {           //        #############
            b = 1;              //            ######
        }                       //        #
        else {                  //        ######
            b = 2;              //            ######
        }                       //        #
    }                           //    #

K&R is similar to BSD, but more compact.

It sometimes happens a situation where one's preferred style doesn't seem to be completely appropriate, say K&R in:

    if( (a > 0) && // ...actually a sequence of long expressions...
        (a < 9) && // ...that takes more than one line...
        (b > 1) ) {
        c = 0;
    }

The block content gets confused with the conditional expression and the whole thing doesn't look quite right. Here BSD style looks better:

    if( (a > 0) &&
        (a < 9) &&
        (b > 1) )
    {
        c = 0;
    }

Although consistency is highly stressed in this document, a little change to gain readability is usually well accepted and in fact desiderable at times. It may seems strange at first to spend time and think just about the way a statement is written, but it is a useful exercise. With practice and experience your insight will grow and, probably, your style will change... that's a good sign!

As this chapter deals only with structure, more tips on choosing a style will be provided in the rest of the document. The examples that have been shown, however, should make it clear that there may be more in a style than its aesthetic value, and that not all styles are the same, though this of course remains subject to opinion.

Top: Table of content  |  Previous: Introduction  |  Next: Style

Copyright (c) 2003 Alessandro Scotti. All rights reserved.