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.
- 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.
- 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.
- 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.
- 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.
- 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
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.