A matter of style

I was dreaming when I wrote this. Forgive me if it goes astray. Like many programmers, I’ve experimented with several coding styles. (But I didn’t inhale.) The point of this experimentation was not simply aesthetic, although I do believe that eye-appeal is important when you’re staring at something for hours a day. Good coding style makes it easier for you and others to understand, debug, and modify your code. It can also prevent bugs from occurring the first place.

In essence, coding styles offer alternative presentations of code that the compiler treats as the same. Compilers, it turns out, have no taste. A compiler wouldn’t care if your entire application appeared all smushed together on one line. That, by the way, is one of the reasons we prefer not to talk to compilers directly; the preprocessor is a much more civilized conversational partner.

In zoological order below, I express my current opinions on coding style, for whatever they’re worth. (Make me an offer.) I of course encourage a diversity of viewpoints, so in the comments to this post I look forward to hearing from both sides on these issues: those who agree with me and those who vehemently agree with me.

Making it explicit

I know what you’re thinking, but get your mind out of the gutter! The headline refers to giving clear indications in your code of things that would otherwise be handled automatically according to the specifications of the language. For example, in expressions with multiple operators, I put parentheses around the sub-expressions, 1 + (2 * 3), instead of relying on the implicit order of operations, although I do make an exception when the main operator is an assignment, sum = 1 + 2. When checking for 0 values, I put the 0 values in my code: if (pointer != NULL), if (pointer == nil), if ([array count] > 0), as opposed to if (pointer), if (!pointer), if ([array count]). I use casts, (int)count, and constant suffixes, 0u, instead of allowing implicit type conversions. This applies to function and method arguments and variable assignments too!

Even if you know the operator precedence and type conversion rules like the back of your hand — actually, I can’t say that I give much thought to the back of my hand — others who read your code might not. When these are left implicit, bugs are destined to arise. In fact, I recently fixed a bug in Vienna where some rows were too short because the methods took floats but the calculations were done as integers, thus truncating the fractional values. Besides, implicit rules can vary from language to language, so if you’re concerned about code portability, or perhaps the sheer effort of mastering multiple languages, why not just free your code from reliance on the linguistic eccentricities?

By the way, I really like the way Java handles logical expressions, using only boolean values. This is definitely a bias due to my background in logic. I want boolean expressions to be real booleans, not integers! My instinctive reaction when encountering if (expression) is to treat expression as boolean, so I don’t want to do a double-take every time just in case I should really be thinking non-boolean.

Goto jail. Do not pass Go. Do not collect $200.

On the one hand, it’s painful to read function and method implementations that consist entirely of nested if clauses. On the other hand, a single return at the end makes an implementation easier to understand and debug. I’ve come to the conclusion, then, that goto is the way to go. I admit that it seems very BASIC, but give it a chance.


-(BOOL)doSomethingWithArgument:(id)argument {
    BOOL success = NO;

    if (argument == nil) {
        goto end;
    }
    statements
    if (condition) {
        goto end;
    statements

    success = YES;

    end:
    return success;
}

Space: The final frontier

I put a space before before and after binary operators, 1 + 2. The only exceptions would be the operators for structure or union membership, a.b and a->b, which I don’t put space around, but you could argue that they are actually binary postfix operators, while other binary operators are infix.

I don’t have a strong opinion about whether to put space after an opening parenthesis and before a closing parenthesis, such as with expressions or function arguments, (1 + 2) vs. ( 1 + 2 ). I tend not to use space in these cases. However, I do have a strong opinion about whether to put space after the asterisk in a declaration: YES! In some cases, leaving out the space is highly misleading. For example, int *array[50] does not declare a pointer to an array of integers but rather an array of pointers to integers, so it’s better to use int * array[50]. The * character already has too many functions — pointer declaration, pointer dereferencing, multiplication — which is why I think it’s best to distinguish them as much as possible.

In the past, I preferred that the opening brace of a code block appear on its own line.


while (condition)
{
    statements
}

I suppose that the logician in me enjoyed the symmetry of opening and closing braces at the same level. However, I’ve come to appreciate the virtues of the other standard.


while (condition) {
    statements
}

Using this style, it’s just as easy to determine the beginning and ending of the code block, and over the course of many blocks you fill a lot less vertical space, which means that you can see more of your function or method at once (which is a good thing). Moreover, there are instances where you want to put something after the closing brace, such as in a do while loop.


do {
    statements
} while (condition);

Therefore, if you want to be consistent, you shouldn’t be opposed to similar constructs elsewhere.


if (condition) {
    statements
} else {
    statements
}

Speaking of consistency, I like to use the ‘shorter’ style for function or method implementations (and even for Objective-C @interface ivar declarations).


type function(arguments) {
    statements
}

It may be true that functions and methods are ‘special’, but I believe that the same considerations apply to them as to other blocks. I don’t understand why developers would deviate here from the coding style used everywhere else.

Party’s over

Oops, out of time.

6 Responses to “A matter of style”

  1. Peter Hosey says:

    “…int *array[50] does not declare a pointer to an array of integers but rather an array of pointers to integers…”

    You might think that you could introduce parentheses to clarify this: int (*array)[50]. But C (or at least GCC) gets this backwards: That gets you a pointer to an array, not an array of pointers. The parenthesized code for what you wanted is int *(array[50]), which of course reads the other way (as a pointer to an array).

    I suppose this is one reason why people don’t parenthesize their declarations.

  2. While I’m not completely against goto statements, in general I stick with the nested if structures. If they start to get too deep, it’s probably a sign that you should add another function call. The use of gotos as you describe usually involves either a layered number of goto destinations at the end of the function, or diligent testing in the “end:” label to make sure everything is properly cleaned up. I prefer nested if loops because I can add the associated cleanup code inside the brackets as soon as I add them, and then fill in the next level of code. And I really don’t think gotos make code any more readable than nested structure.

  3. Steve says:

    I hate dangling braces {
    Very hard to read and match them up. You can spend hours wondering why a simple function won’t work properly.
    I always have them on a line by themselves
    {
    and the code goes here
    }

    And the * always goes next to the identifier, not the type:
    int *x, *y;

    Too many of these () is a waste of my time and yours trying to figure out what is going on. One or two extra for things like (a & b) && (c & d) for those times when you can’t recall what happens first.

    Goto:
    How about:
    if (something bad)
    return kFailure;
    if (something else bad)
    return kAnotherError;

    // good code goes here

    return kAllGood;

  4. Lars says:

    ” The point of this experimentation was not simply aesthetic, although I do believe that eye-appeal is important when you’re staring at something for hours a day”

    Hear, hear! I wish more programmers would take this sentence to heart!

    Among the books[1] I read for my software development, two of the more important ones had nothing to do with programming at all – instead they covered the ins and outs of text design and layout. Reading them gave me an appreciation for how much information can be conveyed by the mere arrangement of text elements. Since then, I try to make the code I write to pass the squint test: if I squint my eyes so that the individual letters would blur into a gray blobs, coud I still make out the control flow of my program. If not, I did something wrong (for example the goto example would fail the test as the goto label is too far indented for its possible uses).

    [1] Since I’m not paid for it, I might as well mention one of them: Robin Williams “The Non-Designer’s Design Book”.

  5. Jeff says:

    Thanks for the comments! You’ve made this the most active thread in the history of the blog. ;-)

    Daniel, I agree that nested if structures are appropriate for some situations. However, a typical pattern is to check for fatal errors at the beginning of a function, and I prefer not have my entire implementation within a giant if clause. If I understand what you’re describing, I think that mid-implementation cleanup code could be accommodated within the goto schema, though of course it depends on the exact nature of the code. To clarify, I am advocating a single exit point rather than multiple goto destinations.

    Another advantage I see with goto statements is that if you customize the labels according to the function, e.g., returnFromDoSomethingWithArgument:, then at any time you can perform a project search and immediately find not only the end of the function but all of the exit conditions for the function as well.

    Lars, the label could appear at the same level as the closing brace, unindented. Another approach would be to use boldface, color, or comments to highlight the label. In any case, the label would always go near the end of the function.

  6. rem says:

    Is this kind of problem where you use goto not a problem where exceptions where designed for?