CSCI-UA.0480-008: Style guide

(This is borrowed from Eddie Kohler's CS61 style guide.)

Style

Coding style refers to some of the literary aspects of writing code. What vocabulary do you use?—for instance, for functions, or for variable names? What spelling and punctuation conventions? What orthography?

Everyone has their own speaking style, their own prose style, and their own coding style. That diversity is great. But some coding styles are worse than others: harder for others to read, harder to maintain. In the conflict between descriptive and prescriptive linguistics, we must be a little prescriptive.

The point of coding style is to make code readable and easily understandable by other human beings (and your future self). The best way to make code readable is to pick a consistent style and stick with it. And the best styles to pick are those with precedent in others’ code. These guidelines can help in that goal.

This guide isn’t about mandatory rules; treat it instead as a set of suggestions. Alternatively, you can follow the “K&R style”, named after its authors, Brian Kernighan and Dennis Ritchie, who created the C programming language; or perhaps GNU’s style guidelines on C.

Example: The Three Bears

What does this code do?

int srev(char*x, char*y) { int l;for(l=0;
y[0];
l++)y++;while(l){*x++=*--y;--l;
}*x = NULL
;}

OK, what does this code do?

int reverse_string(char *the_input_string, char *the_string)
{
   // Function: The characters in "the_input_string" are reversed and stored into "the_string".
   // For instance, if "the_input_string" equals "abcde", then after the function returns,
   // "the_string" will equal "ebcda". The function returns 0 on success and -1 on failure.

   int length_of_string = strlen(the_input_string);
   int position = 0;      // tracks our position in the OUTPUT string
   int reverse_position = 0; // tracks our position in the input string
   char *the_output_string;        // the destination of the copy

   the_output_string = the_string;


   // We want to copy the_input_string IN REVERSE!!! So we need to move reverse_position to the END of the_input_string first....
   for (reverse_position = 0; ; reverse_position += 1)
   {

       // When we reach a null character we are at the end of the string!
       if (the_input_string[reverse_position] == NULL)
       {

            // So we should exit the loop
            break;
       } // end if

   } // end for

   // That loop left reverse_position pointing ONE BEYOND the last character in the string. That's no good!
   reverse_position -= 1;

   // Now run backwards!!
   while (reverse_position >= 0)
   {

       // Make sure we really have a character!!
       assert(the_input_string[reverse_position] != '\0');

       // OK, we have a character.
       // Better copy it to the output string!
       memcpy  (&the_output_string[position],
               &the_input_string[reverse_position],
               1);

       // Great, we did the copy!! Advance to the next position in the output string.
       position += 1;
       // And back up to the PREVIOUS position in the INPUT string!
       reverse_position -= 1;

    } // end while

    // OK, we've copied all the characters into the output string. But we're not done yet!!!
    // We did not copy the last character in the string. Better do that now.
    memset(&the_output_string[position], '\0', 1);

    // Now we're really done!!
    return position;


} // end reverse_string function!

And finally, what does this code do?

/** @brief Reverse the characters of @a src into @a dst, returning the length of @a src. */
int strreverse(char *dst, const char *src) {
    assert(dst && src);  // neither parameter should be NULL
    assert(dst != src);  // we can’t reverse a string into itself
    int len = strlen(src);
    for (int pos = 0; pos != len; ++pos)
         dst[pos] = src[len - pos - 1];
    dst[len] = 0;
    return len;
}

Well, the answer is they all do the same thing: they reverse the input string. But we feel the style of the third example is much better than the styles of the first two. The first example is too terse, the second too verbose, and the third pretty good. Here are some of the problems with the first two examples, and how the third example avoids them.

Example 1

Example 2 Beginning students often err in this direction: making code too verbose.

Example 3: “Just Right” (sort of)

You may find Example 3 harder to follow than Example 2 at first. Learning to read code like Example 3 quickly is a skill, and talented programmers will disagree on whether Example 3 is really “just right,” or too terse. Feel free to write code to your taste! But do think about your style, and think about the points above, and you’ll become a better programmer naturally.

The Golden Rule

Be consistent…

…within reason.

Formatting

Again, it doesn't really matter how you format your program, as long as you do so consistently and apply the same style rules uniformly to your program.

Comments

Commenting is good, but commenting too much can be bad. Even worse, comments need to be updated when code is changed, so having more comments requires more maintenance.

Ideally, you should try to create code that is itself readable and does not require comments. This isn't always possible though, so comments may be necessary to explain especially tricky or complicated sections in your program. Moreover, we have requested that you comment what you write so that we can be sure that you understand it (although, as noted, this is a poor practice in general).

Here are some tips for commenting:

Although not required, one good practice is to use automatic documentation generators. Doxygen will scan through your source files and automatically generate documentation (as html, pdf, etc.), provided that your comments are formatted in a certain way. For Java programmers, this is very similar to Javadoc.

Miscellaneous