Today I ran across an interesting blog entry called Apologies in Code by Tim Ottinger. The basic idea is that most (if not all) comments are apologies for bad code. While I don’t entirely agree with the author, it caught my attention because it describes how I’ve felt about comments from the first day I started coding.

Most inline comments (the sort that come at the end of a statement describing what just happened) are a complete waste of time, as far as I’m concerned. If it’s short enough to add to the end of a line of code, it’s generally short enough to work into decent variable or function names.

But I don’t agree with the zero comments standard he puts forth. Comments have some excellent uses that make working with a piece of code much easier than it otherwise would be. Some examples:

  1. As code separators:

    Separating various phases of a function. For example, vertex skinning involves several distinct yet related steps:

    1. Fetching the vertex’s influences (bone matrices) and blending them together into that vertex’s skinning matrix.
    2. Transforming the vertex position.
    3. Compute the inverse-transpose of the skinning matrix.
    4. Transforming the vertex’s normal.
    5. Renormalizing the normal.

    True, you could write a descriptively named function for each step (assuming each function wouldn’t need half a dozen in/out parameters), but stop and think about that for a moment. If you’re skinning a vertex you’re probably skinning a lot of vertices - plural, very very plural. A tight loop isn’t the place to be calling other functions. And yes, most compilers will inline the overhead away, but what about the debug build? Even if you don’t mind low frame rates while you’re debugging you might not have the luxury of putting up with it. You might be on a console where you have to hit X FPS or else.

    Quick one-line comments separating out the various phases of a function make reading and maintaining it much easier. They serve as brief signals that we’re now done doing x and moving onto y. Very helpful when x is a matrix multiply and y is transforming four points by a matrix - two distinct operations that look very much alike.

  2. Where code simply can’t be readable:

    And that leads me to my next reason to use comments: low-level or highly optimized code. True, compilers can do a lot of our optimizations for us these days, but there are operations that they just can’t handle as well as a human - and these are usually found in a loop of some sort.

    Go stare at a block of SSE instructions. If you immediately see what it does, you either read a comment somewhere, or you’ve spent too much time looking at SSE assembly (and I’m impressed).

    Compiler intrinsics are little better than raw ASM; if it weren’t for the fact that you can name the variables that go in and out of intrinsics they’d be nothing more than semi-portable ASM syntax. Oh, just don’t forget that if you use too many of those variables your compiler might get confused and start moving values out into memory because it’s convinced it’s out of registers…which defeats the purpose of using the intrinsics in the first place.

    This fits rather nicely with what several comments on the original blog entry mentioned: sometimes you have to use an ugly API that makes no sense or lacks documentation or has some hidden “feature” that you’re hacking around, and that bit of code should have a comment on it.

    Otherwise it’s only a matter of time until a refactoring phase eats it as “stale code that must be covering for a bug that’s been fixed since then…because, really, what could it possibly be doing?” And I’m quoting myself there. I won’t trouble you with what I said while reverting my little “clean-up” of the code base. It happens. Tests catch this sort of thing, but a comment would have saved some time.

I’ve also got this tendency to write a big block comment describing what I intend to do, and then write the code that actually does it underneath. I find that helps me stay on track when feature-creepish stuff starts popping up. Usully those comments survive into the final version in one form or another. Often I trim out anything that seems obvious next to the actual code, and condense what’s left into a brief overview of how an API’s functions interact with each other. But these are more about the process than the finished product.

Sorry, comments are closed for this article.