This morning, one of the blogs to which I subscribe gave me this link to a PDF of a scanned book on programming with Smalltalk, Smalltalk With Style, from 1996. One of the authors seems to be one of the Pragmatic Programmers, Dave Thomas.
Now, I'm sure, like me, most of my readers wouldn't be able to read Smalltalk, let alone write it. And, heck, a ten-year-old book? What content could that have that's applicable to programming today? Nevertheless, this book has a whole bunch of excellent guidelines on writing software, some of which are Smalltalk-only, but a surprising number of which are relevant to any language, including C#, VB, and Delphi.
As I said the book is scanned, making it a little difficult to quote at length, but there's a nice summary at the end of the book of all 126 of the guidelines (page 105 of the book, page 116 of the PDF). Here's a little selection, though (the numbers refer to the guideline numbers in the book):
1. Choose names that are descriptive. Well, d'oh, but too often (and I'm guilty of it too) we use brief names over descriptive ones.
7. Avoid naming a class that implies anything about its implementation. A good one this: I've seen classes named something like FooHashtable. Hashtable is way too specific, whereas List or Collection might be better. The aim here is not to allow the user of the class to make decisions about using a class based on its name. Keep it a blackbox as much as possible: that way, you can change the implementation with impunity, say for efficiency or memory usage reasons, later on.
26. Use a temporary variable within a scope for only one purpose. It can be confusing for the maintenance programmer if a variable is used for two different purposes. Also if you do find that you are using a local variable for two different things within a method, it can imply that the method is too large and should be split up into two or more.
30. When you need to abbreviate, use a consistent abbreviation strategy. I'm reminded, with this guideline, of the Command Language (CL) on the IBM System/38 and later the AS/400. The command names were tokenized into 3-letter words (or less), so that DSP meant "display", PGM meant "program", DAT for "data" and so on. Once you knew the standard abbreviations, you could read the command names as English and even be able to guess at command names if you were unfamiliar with a particular feature. Now, I'm not recommending that we go back to this way of naming commands, just that if you were to use abbreviations in names, be consistent and if necessary spell it out somewhere so that the whole team can understand that "Str" always means "string" and someone doesn't decide to use it for "setter" or something like that. (This guideline's concept continues for guidelines 29, 31 - 34.)
36. Do not comment bad code, rewrite it. If you find yourself commenting some code because it's unclear (though do note guideline 47 below), consider the possibility that it's just badly written and that it should be refactored in some way.
45. Avoid relying on a comment to explain what could be reflected in the code. This goes directly to the readability of the code. If you choose your identifiers well, code can read a little like English and you don't have to write an explanatory comment.
47. Comment the steps of an algorithm, as needed. An algorithm, unless it's one of the really well-known ones, tends to be fairly obtuse. Document such an algorithm with a reference to a standard algorithms book, or by detailing the steps in the algorithm and why they're done in that order.
76. Avoid altering the behavior of well-known messages. By "messages" here, Smalltalkers mean methods, and by "well-known" I'm going to assume "what the Framework does". So, as an egregiously bad example, don't write a method called Contains() that adds the key being searched for if it wasn't found: you would be confusing the reader of the code who would make the natural assumption that your Contains() would work in the same way as other classes in the Framework. Rubyists tend to refer to this as the Principle of Least Surprise.
79. Write small methods. If I'd been paid in the past by the line for code reviewing every stupidly long method, I'd be sipping margaritas on a white beach in the Caribbean, wondering if my private Lear jet was ready to take me to Whistler. I just don't understand the fixation some developers have for the long method. Do they see them as somehow more macho?
87. Try to design subtypes instead of subclasses. This is essentially an argument for interface inheritance rather than implementation inheritance.
104. Test classes as they are developed. Oh. Wow. Cool. Yes.
As I said, that's just a small selection. I'd at least browse through the guideline summary, jumping back into the main body of the book whenever needed. Although I did say I couldn't read Smalltalk, I was partially joking: a lot of the code the book is fairly approachable.
(Hat tip: Ben Griffiths)