Coding Standards

These are some personal coding standards that I use. I like to read other people’s coding standards and try to pick up good ideas from them, so I thought I’d post my personal preferences up on the Web too. If you disagree with any of these, by all means give me some feedback, but keep in mind that these are personal standards!

  • Use descriptive names. Don’t use abbreviations, e.g. call a variable maximumNumberOfItems rather than maxItems.

    Rationale: Abbreviations are harder to parse and can be inconsistently abbreviated. Is it maxNumItems or maxNoItems? Does maxNoItems somehow mean “the maximum of items not allowed?”

    This is largely at odds with usual C, C++ and Haskell culture, where short function names are the norm (strcpy, std::, fst). A side effect of this is that 80 columns probably isn’t going to be enough for your editing window; you will likely need at least 100 columns or 132 columns. Of course, the corollary to this is that it was probably the 80-column terminal width limit that caused so many abbreviations in the first place. About the only abbreviation that I ever use is RegEx instead of RegularExpression, since it’s one of the very few abbreviations that are well-understood and also easier on the brain to read.

    If you’re going to complain that these long variable names are tedious to type, you need a better editor. Text editors have had completion since, like, the 1960s. Vim users have Ctrl-N and Ctrl-P; Visual Studio boys have IntelliSense; Xcode folks have Esc and Opt-Esc; Emacs users have the Holy Avenger of Completion (all praise Dynamic Abbreviation!), M-/.

  • Brackets always go on their own lines:

    if(condition) { statement1; statement2; } else if(condition 2) { statement1; statement2; } else { statement1; statement2; }

    Rationale: I find the above much easier to read than this:

    if(condition) { statement1; statement2; } else if(condition 2) { statement1; statement2; } else { statement1; statement2; }

    Code is a form of typography: visual presentation is a large part of how you’re trying to communicating an idea. By putting brackets on their own lines, you’re using spacing—one of the most powerful elements in typography—to separate semantically distinct elements.

    • Converse to the above, I like to put single statements for if() branches on their own line with no braces, like so:

    if(condition) body; else if(condition2) body2; else body3;

    Rationale: Your statements are compact, so make them look compact. No need for braces on a one-line statement.

    • Use visual comments to separate semantically different groups of declarations. I personally use these two separators:

    Major: //*************************** Minor: //—————————————————————————————————————-

    Rationale: Greatly improved clarity. As an example, the start of a C++ implementation file for me might look like this:

    //***************************

    include

    include “Foo.h”

    //***************************

    void Foo::Blah() { blahblahblah; }

    //***************************

    • Be wary of too many nesting levels of braces. If you’re nesting that deeply, either (1) invert if() conditionals to break or return out of a loop or function early (see the note below about RAII and exceptions if you need to clean up stuff), or (2) move some of the nested code into a separate function.

    Rationale: Having code start at column 40 in your screen wastes space and makes it very hard to understand control flow. Obtuse control flow is always the hardest thing to understand. (There’s a reason why recursion and continuations are were hard to grok!)

  • If you need to clean up resources before exiting a method and you have multiple return points—and I have nothing against multiple return points—use the finally clause of an exception to clean up, or use the Resource Acquisition is Initialisation (RAII) idiom in C++.

    Rationale: I think multiple return points are fine. The alternative to multiple return points is creating a mutable variable that indicates some sort of state, and then you have extra conditionals to worry about, resulting in a combinatorial explosion of code paths once you start having three or more conditionals. That’s even worse. Of course, now that you have multiple return points, you may have to write the same cleanup code at every single return point. This is bad: cleanup code for the function should be guaranteed to be called before the function exits, otherwise you might forget to add the cleanup code when you add a new return point. (Assuming you’re the one adding the return point; think of the poor maintenance programmer after you.)

    Both the C++ RAII idiom and the finally clause of an exception handler will guarantee running some specified code when the function returns (assuming your language has a finally handler, of course). For the latter, simply wrap the entire function in a try block, and put your cleanup code in a finally block.

  • Use const qualifiers as much as possible in C and C++. (If I were to design a language, const variables would be the default!)

    Rationale: you want const for the semantic guarantee it gives to you, not for some bollocks compiler optimisation that’ll likely never happen anyway. By declaring a variable const, you have a formal guarantee that the value set at that line in the source code will always be that value. If you need to change a variable’s value, just make another const variable based the original value and apply your change to that. Almost every local variables in all my source code is const except for iterators and loop indexes. You can’t use const everywhere, such as when an underlying library isn’t const-friendly (e.g. Cocoa) or when you can’t take the performance hit of lots of value copying, but try.

  • Prefer positive logic in conditionals to negative logic. e.g. Instead of this:

    if(secondaryCategory != nil) [secondaryCategories addObject:secondaryCategory]; else break;

    write this:

    if(secondaryCategory == nil) break; else [secondaryCategories addObject:secondaryCategory];

    Rationale: It’s easier for brains to parse positive logic. Unless you don’t think it’s clearer. (See what I mean?) Use this judiciously: if the negative logic is actually better for control flow reasons or whatever, use it.

  • André´s Golden Rule: if you need to comment a block of code to say what it does, move that block of code into a separate function and name the function well to say what it does.

    Rationale: If you name things well, you’ll need a lot less comments. Less comments means less possibility for code/comment mismatch, and also makes the code easier to read because you don’t have comments every five lines explaining what the previous five lines did. I dunno about you, but I’ll take an uncommented header file with long descriptive variable and functions names over a JavaDoc-commented header file any day.