Programming Style Guidelines
Every program should have the following:
- a header
- comments describing parts of the code
- appropriately named identifiers for variables, constants, and functions
- constants in place of "magic" numbers and values
- judicial use of whitespace
- an 80-character line width
Check out these examples to get an idea of why style matters.
Note that this page uses C++ example in many places. You can use these guidelines for just about any language, however.
Every one of your program files should have this comment at the very top of the file. This is helpful to you and me. For instance, if you look back at a source code file several weeks (or months or years) after you've written it, this header will provide you with the context of the program.(Back to top)
You should use comments in your code to ensure it is understandable. It is important that larger blocks of code, even if they are easy to follow, are preceded by a comment summarizing the goal of the following code. For lines or small blocks of code that are confusing, it is helpful to have comments that make clear the confusing bits. Comments should not describe the code itself, but rather the goal of the code. Here's an example of good commenting and bad commenting:
// Assign 'Alice' to a variable named 'name'. string name = "Alice";
// Alice is the name of the heroine in our adventure game. string name = "Alice";
One common style for function comments is JavaDoc format (which can also be used with the Doxygen documentation generator). This style has annotations that allow an external program to be run over the source code to build documentation pages in HTML. The basic format is:
You should have one
@param annotation per incoming parameter and
they should be listed in the order specified in the function signature. The
@return annotation should occur last and should only be included if
the function returns a value; i.e., do not include it if the return type is
- Be sure include comments in the following places:
- at the top of each file describing the overall purpose of the code
- above each function, describing the purpose, inputs, and outputs of the funciton
- above each large, cohesive chunk of code, describing its purpose
- above small, confusing chunks of code where it may not be immediately obvious what is going on
- Ensure your comments are grammatically correct—use the correct punctuation and capitalization
Appropriate Identifier Naming
Identifiers are the names you give to elements like constants, variables, functions, and classes, and they should make clear what the element is and does. Identifiers should be concise, consistent, and readable. What does that mean?
Identifiers should be as short as possible while still clearly conveying the purpose of the underlying element.
Consistency means that multiple identifiers referring to relative levels of
concepts should show that relativity in their names. For example, if a program
has variables for a customer's first and last name, well named identifiers for
these two variables are:
lastName; poorly named identifiers are:
In the poorly named case, it's unclear looking at
name to know how
it differs from
lastName (is it the first name, whole name, middle
name, nick name, ...?).
You should avoid abbreviations, uncommon acronyms, and single characters (unless
appropriate, such as using
x in a math function or
in a for loop). Studies have shown that expanded identifiers make it easier to
comprehend code blocks. In addition, use clear delimiters between words within
an identifier, e.g.,
maxoveralscore is much harder to read than
Constants in place of "magic" numbers and values
It's tempting to add arbitrary hard-coded values to your code. For instance, consider a program to check if a user provided number is less than some threshold, and then divides that number by some value (it's a weird program...). You might write the program as follows:
In this version of the program, I happened to set both the threshold and the divisor to 10. These are called magic numbers because there doesn't appear to be a reason they were picked, and they are hard-coded directly into the center of the program. There are two major issues related to comprehension and maintainability with magic numbers that this program illustrates.
First, it is unclear how the 10's are related. Is the 10 in the if statement the same 10 at the bottom of the program? If I want to change the threshold, should I change the divisor, too? It's unclear!
Second, if I do want to change either the threshold or the divisor (assuming I know which is which), I have to change it everywhere in the code, including in the comments. For each, that means modifying two or three lines of code.
Now we know 1. what code uses the threshold value vs. the divisor value and 2. if we want to change either value, we need only update one line of code at the top of our function. Easy to read, easy to comprehend, and easy to modify!(Back to top)
Judicial use of white space
White space includes brace placement, spacing between lines, and indentation. The convention we use in this class is to always place curly braces on their own line, indented to the level of the code outside of the curly braces. Inside of the curly braces, everything should be indented one tab more. I usually use four spaces per tab. Code that is aligned is significantly easier to read.
Also, add in blank lines between chunks of strongly related code. In the good examples below, I put a blank line between logical segments of code. The rule of thumb I use is, one blank line above every comment.
Or, with the curly braces removed because the block only has one line:Bad (Back to top)
80-character line width
A standard CLI is 80 characters wide. Even though I do most of my editing in a
text editor rather than via a CLI, I still use 80 characters as my limit. Text
that is longer than that auto wraps, but often not in a way that is easy to
read. In Sublime Text, it's easy to set up a ruler at 80 characters. This lets
you see how close you are to hitting the limit. Go to
80. Remember that
you can spread long C++ statements across multiple lines!
Take a minute to think about what this next program does:
Now take a look at this functionally-equivalent program that is styled using the guidelines above:
So what did I do here? First, I added a header, which lets everyone know what the program does. Now I need only read to the second line and see the file name is
average.cpp to have an idea of what it does. The description field makes it obvious. I've also added a function comment above
main. I've created concise but descriptive identifiers for each variable—
total keeps track of the running sum, while
userNumber is a number entered by the user. Through judicial use of whitespace, blocks of code are now indented consistently, making it easy to tell when I'm in a function or for loop. I've used blank lines to segment chunks of related code, making the flow of operations easier to comprehend. I added some extra output to the user to make it clear what's expected. Finally, I've used a constant to keep track of the number of values to read in from the user. This relates all instances of
NUMBERS_TO_READ to the same conceptual meaning, and also makes it easy to change the value to something else (otherwise, we'd have to manually replace every instance of 10 in the code).