Designing for readability

Raymond Chen writes, “Design for readability,” arguing that it’s important to write code with the expectation that it’ll have to be read and understood by someone — perhaps even yourself — sometime later. Daniel Jalkut replies to suggest isolating unreadable code and that it’s OK if some of your code is unreadable.

As much as I hate to disagree with Daniel, I’m in complete agreement with Raymond here. Maybe this is because nearly all of my experience is as a system software generalist. Most of my career — on Java, Rotor, the Intel project, and what I’m doing today — has been spent working on code on platforms or in environments where its original authors never expected it to run. That means I’ve spent lots and lots of time over the years trying to understand how someone else’s code behaves, then figuring out the right changes I need to make to get it to work in my environment. I’ve also frequently had to improve code in ways its original author didn’t expect, which is essentially the same problem.

In all of these cases, well-designed readable code makes a huge difference. It can be ported or improved faster and with less risk, and the resulting changes, if done right, are themselves far more maintainable in the future. In some cases this has been the difference between a single 5-minute change and weeks of work plus ongoing maintenance for me and other engineers. It’s a very big deal.

In short, readability, clean design, and good comments are very important. The time you spend making your code readable will almost always been a benefit in the long run.

9 Comments »

  1. Daniel Jalkut Said,

    April 7, 2007 @ 6:39 am

    For the record, I am also in (nearly) complete agreement with Raymond. I mainly disagreed with his premise that code is read more often than it’s written. I don’t think that’s true.

    And my opinions about this also come from being a code generalist. In particular, I think of the bugs I fixed in the Mac OS 7-9 days, when some of the ugliest, unreadable code imaginable was involved in the fixing. Often it was the skimmability of the outer layers that made it possible to pinpoint a bug, even if the final fix required cracking open some C file that was autotranslated from Pascal that was auto-translated from 68K Assembly.

    In short: a giant code base is referenced much more like the yellow pages than like a novel. In the phone book, it’s nice when all of the entries are readable and well designed, but it’s much more important to be able ot skim to the section you’re most interested in right now.

  2. Michael Rawdon Said,

    April 7, 2007 @ 9:36 am

    I’m a fan of readable code and good comments, too. I try to comment the hell out of my code, although I feel like I do a poorer job of this than I once did. Maybe I’m getting jaded. (Or maybe I comment as much as ever and it just feels less adequate the more experience I gain.)

    I have heard some people express the opinion that comments can actually be detrimental to code - especially evolving code - since comments tend not to be kept up to date as the code evolves, and therefore becomes an inhibition to understanding the code. In a way I can understand the rationale behind this, but overall I think it’s a lose not to comment: At the very least, providing an indication of the intent behind the code at some point in time can be a good starting point, and the change logs (assuming you have them) can help you get up to date.

    But overall, more information == good.

  3. Ask Bjørn Hansen Said,

    April 7, 2007 @ 5:36 pm

    Michael,

    You can only “see” (from lack of screen size or mental capacity) so many lines at a time when you are reading the code, so an “obvious” comment is a waste of screen and mental space. I find the best reason not to add a comment is just that it’s an extra line of data.

    Possibly then you are commenting less now because your experience helps guide you to where the comments are helpful and where it’s just extra data.

    - ask

  4. pwb Said,

    April 8, 2007 @ 12:15 am

    It’s not about commenting (which Raymond didn’t even mention, btw). It’s about readable code.

  5. Reinder Said,

    April 8, 2007 @ 5:27 am

    You write:
    “I’ve spent lots and lots of time over the years trying to understand how someone else’s code behaves, then figuring out the right changes I need to make to get it to work in my environment. I’ve also frequently had to improve code in ways its original author didn’t expect, which is essentially the same problem.

    In all of these cases, well-designed readable code makes a huge difference.”

    I agree with that, but at the same time, I also am somewhat in Daniel’s camp. Why would _I_, now invest in making my code more readable, on the off chance that _you_, somewhere in the future might reap benefits from that? Sometimes, I leave a wart on some code because I figure that it is not worth fixing it now.

    Oh, and comments are bad if they tell anything about what code does, good if they describe why it does what it does. You should always be able to have your code express what it does without resorting to meta-info such as comments.

  6. Steven Noyes Said,

    April 8, 2007 @ 8:39 am

    I tend to agree with pwb. You can comment the heck out of code and still not have it readable. I spend most of my time doing maintenance (Boring but it pays the bills) and get to read lots and lots of code. Some of it stuff I wrote 3-7 years ago. Much of it stuff I have never seen. I have found things like:

    dataisfresh harder to read than either data_is_fresh or DataIsFresh or isDataFresh. Likewise, correct and consistent use of indentation and white space can make a HUGE difference. I have also seen inappropriate optimization. Areas where the code gets very complex branch wise to save 0.01% of the processor while leaving a memory move loop completely un-optimized that might be worth 2-3%. These are the TRUE areas of readability IMO.

    Comments (the absence or existence of) tend to be the least of the issues.

  7. Chris Adams Said,

    April 8, 2007 @ 7:02 pm

    I’ll second Steven’s comment: one of my favorite examples was a website we (the design firm) inherited from a major consulting company after our mutual client gave up on their ability to complete it.

    The code might have seemed “best-practice” in many ways - nicely indented, declared variables, tons of comments, detailed changelogs, use of functions for common database tasks, etc. It took me a surprising amount of time to figure out what some of the code was doing because I couldn’t believe that the same programmers hadn’t used a single WHERE constraint, much less a JOIN, in any of their SQL and were instead processing entire tables in nested VBScript loops and they’d never thought of using functions to encapsulate non-database features like generating common HTML blocks or reusing those functions in site-wide include files rather than duplicating them in each page.

    This was absolutely corporate-standards-compliant code representing something like a man-year of labor and it was horrible because there was so much complexity that it was almost impossible to understand what it was doing. Once I refactored it the codebase had dropped to something a third of the original size despite having added some major new features - and removing most of the comments because perhaps 10% of them told you anything which wasn’t obvious from the variable/function names.

  8. Blain Said,

    April 9, 2007 @ 12:11 am

    Agreed that readable code doesn’t necessarily mean commented code. Readable code is how. Comments are why. I’d much rather have the code sparsely commented but well-written and the comments focusing on what the sections conceptually do.

    x += y; /* Add y to x */ does nobody any good. You know it, I know it, and it’s the first type of comments to go out of sync. Ideally, X and Y should be replaced with longer, more descriptive variable names. But even then, instead of the useless comments, a five-line block explaining what the function should be doing, what variables we really care about, and a link to a page that has the general algorithm would be a world of help. And they rarely change, definitely not as fast as code, so that it’s less likely to have the documentation get out of sync.

    As of late, I’ve taken to using temporary variables just to add to readability, trying to break myself of false optimization habits. A younger me would have:

    if (!ComplexFunction(With,Lots,OfArgs)) {…}

    Instead, it’s more readable to have:

    BOOL success = ComplexFunction(…Spread out along multiple lines if necessary…);
    if (success == NO) {…}

    Correct me if I’m wrong, but wouldn’t the compiler note that the temporary variable is only used temporarily, and that it feeds immediately into the if? And then, since NO is constant at 0, it could drop that CMP and simply do the jump if nonzero like the first would? That is, won’t these both compile into the same binary, more or less? And the terseness of the one-liner was all for naught?

  9. Commented Code Doesn’t Equal Clear Code | David Paul Robinson Said,

    April 9, 2007 @ 6:44 pm

    [...] Out of Cheese and Daring Fireball. Share [...]

RSS feed for comments on this post · TrackBack URI

Leave a Comment