Seven rants about successful programming, give or take two

A friend of mine has sent me this list with the Seven Secrets of Successful Programmers and asked for comments. Halfway my reply, it’s occurred to me that i might as well post them here and, hopefully, hear about your opinion too.

First of all, i’m wary of magic recipes and fast-food solutions. There’s no such thing as a quick recipe to become a proficient programmer. It takes effort, a lot of hard work. No secret list will spare you that; as we all know, there’s no silver bullet. Not that we can’t use a little help from more experienced programmers and hear their advice, but short rules of thumb are often problematic. Software is, well, soft, and it’s very difficult to come up with eternal truths to be carved in stone. I prefer the whole story, as recounted for instance in books like The Practice of Programming, or extended guides like Norvig and Pitman’s classic tutorial on Lisp style.

Don’t take me wrong. I don’t think there’s anything evil in trying to convey hard won lessons in little capsules. Otherwise, i wouldn’t be writing these musings in the first place. It’s just that i dislike oversimplifications; they go hand in hand with the notion that programming is just something to be done by underpaid coding monkeys, or that it should be as easy as clicking around with a mouse.

But let me turn back to the original purpose of this post, which was, oh yes, commenting on those seven recipes to success. Here’s my take on some of them.

  1. Code for human consumption. Dead on. I haven’t much more to add here. As almost a corollary, using an as higher as possible level language is a non-brainer. This secret is nicely expressed in SICP’s preface:
    Programs must be written for people to read, and only incidentally for machines to execute.

    But of course, really grasping what that means takes reading SICP, at least.

  2. Comment often and comment well. Sorry, but this one is completely misguided, at least in my book. I’m not refering to the comment well bit (which, as an aside, is as vacuous as you can get), but even here the secret’s author gives a bad example:
    Good comment: Disable button to prevent its activation
    Bad comment: Set cmd = False

    The bad comment is obviously bad, but the proposed solution is far from good. Code is to be read by programmers, not by nincompoops, and we all know that a disabled button cannot be activated. The problem in the above example is not a bad comment, but very bad variable naming: use isActive instead of cmd and comments are unnecessary. As they should be. Which brings me to the “comment often” part, which the author reinforces with this incredibly bad piece of advice: comment your code so that it can be understood just reading the comments. Beg your pardon? What happened with our rule number one? (and no, comments are not code).

    In my experience, the need to explain what a snippet of code is doing with a comment is a sure indication of bad coding. Good code is self-explanatory and needs few, if any, comments. Otherwise, you did something wrong, be it bad naming or poor function breakdown. Not to mention the issue of keeping comments and code synchronized during rewrites. So here’s my secret number 2: comment seldom, write self-documenting code instead. This will make your programs not only easier to understand and maintain, but of better quality.

    Of course, this does not imply, by any means, that documentation is not needed. Proper documentation of your public interfaces and modules, how they work together and their dependencies is a must (this being, by the way, one of the things i dislike about extreme programming and other agile methodologies). But it does not belong into your implementation’s comments.

    There’s a lot to say about how to properly document your code, and often the language you’re using influences the documenting style (for instance, via its abstraction constructions (modules, interfaces, protocols, categories, whatever)). Although i won’t discuss this issue further, i’d recommend reading this very interesting discussion over at comp.lang.smalltalk, which incidentally demonstrates how difficult is to come up with cure-all rules of thumb.

  3. Layout code to increase legibility. But of course. I am however quite surprised that anyone can list such an absolutely basic thing as a secret to success. If your programmers are not able to write properly laid out code… well, you’d better forget about success in the first place. An important consideration in this regard, though, is that your tools should make this task trivial.

    As in many other things, Emacs excels in this regard, making indentation and code layout a breeze. I won’t try to convince you of using Emacs, but if your only quibbles about it come from using and learning it for less than a month, please consider giving it a serious try. These comments may help you realize what’s in store for you; and, if you love programming, chances are you’ll appreciate the beauty and power of its design. The learning curve is steep, but again, you know what i think of those looking for easy solutions ;-)

    Whatever your final decision (there’s nothing wrong in using VIM if you like it better), please learn to use your editor and exploit all it has to offer. It’s your basic tool and it should be customizable and extensible enough to exactly match your needs and make your life easy. Don’t write Lisp using Notepad.

  4. Expect the unexpected and deal with it. Absolutely. I don’t have any quibble here. Error handling may well be the most difficult task we face during program construction. Elegant code for the nominal case is, in comparison, a piece of cake. When you introduce error handling code, things get messy with extraordinary ease. During all these years, i’ve had a very hard time writing error handling code that looked elegant, not to mention beautiful. Actually, i think i’ve yet to find the right way to tackle exceptional situations. Non-resumable exception systems a la Java/C++ often have caused me more problems that simpler mechanisms (like return values and design by contract with assertions), probably due to their non-local nature. Much more usable are Common Lisp’s condition system and Smalltalk exceptions. Taking a look at them, even if you’re not using those languages, is a healthy exercise that may change the way you think about error handling.

    I won’t venture any further advice (for now) on this thorny issue, except for one recommendation: plan your error handling strategy in advance, for it is not something that can be added easily to your program as an afterthought.

  5. Name your variables to aid readability. Sure, and we’ve already seen how important this is for self-documenting your code. But i thought it was clear by now that Hungarian notation is evil. If you want good type checking, use a decent statically typed language like Haskell; with dynamically typed languages, well, using prefixes to mark the type of an identifier is non-sense. Even in languages like C or C++ there’s much to say against this notation, if only for the fact that it defeats the much more important goal of readability. Josh Fryman summarized long ago my feelings on Hungarian notation in his nice article on coding standards, by stating his
    Theorem One:
    Hungarian Notation exists to make up for bad coding practices.

    At any rate, the secrets author is very right to stress the importance of consistency and uniform conventions. In this regard, i’ve also found useful the practice of adding a bit of metadata to a variable name’s to indicate its scope (static vars in C/C++, members in C++, Java or Objective-C, special variables in Common Lisp…). In an ideal world, my programming environment would be aware of this kind of metadata and automatically provide some kind of visual clue, but we’re not there yet.

The last two secrets are an exhortation to use short functions (that do just one thing, and do it well) and lexical scope. Very good advice, without further qualification. I’ve found that functional languages, specially those in the Lisp family, and, more generally, having closures at your disposal naturally reinforce these desirable qualities of the software i write.

Summing up, my feeling is that, important as the above issues are, they only scratch the surface. If i had to give you a single rule in your path to become a good programmer, it would be to never stop learning. Read a lot, and then more. Be proficient with at least 3 or 4 languages and 2 or 3 paradigms. Have a good grasp of how their compilers or interpreters are implemented. And find your own rules.

Happy hacking!

Posted in Essays. 24 Comments »

24 Responses to “Seven rants about successful programming, give or take two”

  1. lb Says:

    >”Code is to be read by programmers, not by nincompoops”

    love it!!

  2. Reinier Zwitserloot Says:

    Oh, amen to all of it. Kudos for shooting the original full of holes, though the conclusion that he was an idiot was quickly made already. Still, for those who didn’t have the experience to realise it was a dumb combination of the obvious, the vucuous, and the mistaken, this should help.

  3. Chris Perkins Says:

    Error handling, in particular, is one of those areas that I feel no programming language or methodology has really gotten right.

    For starters, there are the various known ways of handling errors (return values, exceptions, restarts, etc.) but not a common practice on when each should or should not be used. And this applies to error detection and error prevention as well.

    Personally, I feel that there is a large class of errors which are orthogonal to programming and should/could be handled very differently than the way we do now, though I lack the creativity to imagine exactly how. In my gut, I feel that the elegant code for the nominal case, as you say, _should_ be enough to suffice. That the labored necessity of error handling points not to a fault with my code, but instead with a fault in my tools and languages.

    The only clue I have to any of this is that there is a lot of metadata that no language exploits. I have so much more knowledge about my code than I am able to express to my compiler or runtime environment. Instead I try to sum it up into contracts and catch errors that way, but I really feel like there is a missed opportunity that my tools and languages aren’t exploiting. That catching errors is a poor substitute for preventing them.

    Chris
    P.S. Nice blog, glad to see that you are back it at again!

  4. Otsuna Says:

    The purpose of comments is to explain not the what and how, which should be obvious to even the most simian of coders, but to explain the *why*; often in short production cycles certain hacks are neccessary to ship product. When we’re on the bug hunt we don’t need code paraphrasing, we need info on why that code is there in the first place, especially if it’s a hack, since further modifcation to the code, or it’s surroundings can cause bugs to resurface. (If the modifcation was entirely in the correct context, it wouldn’t be a hack, and would likely need no comment, given proper naming)

  5. Jim McCoy Says:

    Ditto on what Otsuna said. I often find myself writing comments in code where the flow of execution is self-evident as a means to let other people know what some of the external calls are doing (usually to win32 bits accessed from Python…) What a chunk of code is doing should usually be obvious, why something is being done at a particular point in the code usually requires a big-picture understanding of the entire process. Sometimes the person diving into a section of code has not had time to follow every bit of included code or wrestled with the six different ways of performing a specific task enough to know that the five obvious ways to accomplish something are not going to work in this specific case.

  6. Bruce Hoult Says:

    “When we’re on the bug hunt we don’t need code paraphrasing, we need info on why that code is there in the first place, especially if it’s a hack”

    Why it’s there in the first place? That’s more properly determined by:

    - doing cvs/svn annotate to find out who wrote it and in what revision

    - going to cvszilla or one of the many web intefaces to cvs/svn to find the checkin comment for that revision and what other changes were made at the same time

    - going to bugzilla and finding what task these changes were made as part of.

    This works for any line of code, bot just ones that someone thought to put a comment on.

    Don’t have integration between bug tracking and source code repository? Shame on you. If you’re using bugzilla with cvs or svn then go directly to http://www.cvszilla.org/

    As a real live example, see:

    http://www.opendylan.org/cvszilla/transaction.cgi?id=9202

  7. Merrion Says:

    Reiner – I will thank you not to call me vacuous until you can spell it.

    My example on comments perhaps didn’t make the point I was trying to make which is that comments are to tell you what the code should be doing (intent) whereas self-documenting code can only show what the code is doing (action).

    For examples of bad code due to layout there are rich pickings in the world of SQL – I have seen a good number of unindented blocks and select statements that just flow on and on. It does happen and while it does there is value in advising against it.

  8. muro Says:

    better keep silent and be thought for a fool than speak up and remove all doubt.

    Somehow, I think many people will think after a few years of experience that they achieved mastery. So they start to give advice. Unfortunately, only from comments of others they learn they are far from it.

  9. muro Says:

    Oh, I was talking about the original (linked) article :-)

  10. Programming Rules of Thumb « Random Musings Says:

    [...] The facts is there arn’t any, as I found in this excellent post. Kudos to WordPress (again) for their dashboard which directed me to this post. [...]

  11. Johan Tibell Says:

    I feel that Haskell’s Maybe type might be the way to go for some of the error handling. The one solution I’ve found isn’t particularly ugly. I guess it’s somewhat simmilar to nullable types.

  12. Kalle Edvinsson Says:

    On the issue of Hungarian Notation, I completely agree that the “popularized” version is abominable.

    However, http://www.joelonsoftware.com/articles/Wrong.html, I found to be a rather enlighting and nuanced view of the intentions of its original creator. And they don’t seem too bad at all, actually.

  13. Damyan Pepper Says:

    “In an ideal world, my programming environment would be aware of this kind of metadata and automatically provide some kind of visual clue, but we’re not there yet.”

    I’ve got something similar to this in my .emacs that makes my programming environment know about the prefixes.

    (font-lock-add-keywords
    ‘c++-mode
    ‘((“[^A-Za-z0-9_]\\(m[A-Za-z0-9_]+\\)” 1 font-lock-type-face)))

  14. jao Says:

    Damyan, yes, i’ve got something similar in my .emacs. But i was referring to the environment detecting a variable’s kind without my telling it (via a prefix or any other means).

  15. Merrion Says:

    Breaking news – there are now eight ‘secrets’ ;-)

  16. Nick Thomas Says:

    Bruce Hoult: Why all the extra hassle? Isn’t it a lot easier (for both the code author and reader) to just have that documentation right in the code, rather than in some database somewhere else?

  17. Programming Advice « Nimish Batra, The Life and Times of Says:

    [...] Response: Seven rants about successful programming, give or take two [...]

  18. lionel Barret Says:

    the comment rule is quite stupid indeed.
    But in complicate language (think c++ opposed to python), it is a good habit to write the comment then only the code.
    The comments written help the good naming of variables and functions.
    In the end, just delete the unnecessary comments.
    it’s from code complete if I remember correctly.

  19. Merrion Says:

    Whilst I am a big fan of clarity in source code I don’t believe that the code can be totally self documenting because the source code can only tell you what a program does, whereas a comment can tell you what the intention of the person writing that code was.

    Additionally the source code is only self-documenting to someone who has a good knowledge of the programming language that the source code is written in. However it is often the case that the person who has the best understanding of the problem space (be they a business analyst, end client or whatever) does not have sufficient developer experience to be able to read the code itself.

  20. Abhijit Nadgouda Says:

    Nice post. Regarding comments I think that comments should be used to mention the problem the code is trying to solve. Code is the solution, comments should complement it by documenting the problem. How detailed it should be depends on the problem and the team.

  21. BrianWill.net » Blog Archive » More coding practices religion Says:

    [...] Seven rants about successful programming give or take two. [...]

  22. arsenalist Says:

    [...]Non-resumable exception systems a la Java/C++ often have caused me more problems that simpler mechanisms (like return values and design by contract with assertions), probably due to their non-local nature.[...]

    I don’t know about that. Having return values that indicate one of success or failure is one thing but you’re opening a can of worms with that. When there are more than one reasons of failure and each failure event has data attached to it, it becomes way more complex using return values to indicate this rather than exceptions.

    Here’s some links:

    http://today.java.net/pub/a/today/2003/12/04/exceptions.html
    http://www.onjava.com/pub/a/onjava/2006/01/11/exception-handling-framework-for-j2ee.html

  23. Marcin Says:

    On hungarian notation – As Joel Spolsky comments, the original intention was to make up for bad type systems, by allowing code writers and reviewers to more easily see when two variables of the same machine type are not of the same type (e.g. ints used for heights and ints used for weights).

  24. Jay Says:

    “2: comment seldom, write self-documenting code instead”

    Self Documenting code is a serious oxymoron. Sadly too many people do this and create disasters when they quit and leave the rest of us to pick up the pieces. One persons “self documenting code” is another person’s headache / garbage.

    I agree with your statement about documenting routines. Here is where you should describe the function.

    Lets be honest. I think most people avoid comments because they hope to create a program that they alone will understand and have a lifetime job maintaining. Or they are so ashamed at their lack of ability that they don’t want to spell out the awful crap they write so that others can pick it apart.


Leave a Reply

Gravatar
WordPress.com Logo

Please log in to WordPress.com to post a comment to your blog.

Twitter picture

You are commenting using your Twitter account. (Log Out)

Facebook photo

You are commenting using your Facebook account. (Log Out)

Connecting to %s