1. Favor commenting why over how. It may be clear how your function works, but it's rarely self-evident why you chose to use a particular technique -- another will probably seem (perhaps correctly) like a better choice to someone else. Subtleties of design choices and lessons learned from mistakes are much harder to just infer while looking at code than surface details about how it works.
2. If you're about to write a comment, see if better names make it unnecessary, or if breaking a section of a function into a named subfunction clarifies things. (The corollary being that there's nothing keeping you from naming all your stuff "dude" and "heyHeyHey" besides bitter experience and the eternal scorn of your peers.)
3. Consider using asserts, tests, or the type system in place of some comments - they're like comments, but they're actually checked.
4. Consider datestamping any comments more than a few words. (Do it automatically, with an action in your editor.) It only takes a few characters, and sometimes it will be unexpectedly helpful. (A good VC system can help you track down when a given comment was added, of course.)
I'm with you on 1-3, but #4 seems wrong. What purpose is there to knowing when the comment was added if you don't know when the code was written[1]. This just looks like a trick you've developed to try to figure out when a comment is lying to you. But if you have so many comments that you doubt their veracity, you have too many comments. Read the code for truth.
[1] Without, as you mention, using your SCM system. But I'd argue strongly that if you can't do the equivalent of "cvs annotate" from memory, you're using the wrong system or you don't understand it well enough.
In my experience, it has been helpful in untangling contradictory changes based on changing customer specifications over time. Mostly, I think it's worth doing because the cost of doing so is really, really low (e.g. a hook to your add-block-comment function, a few characters), but there are edge cases where it's very helpful. Take it with a grain of salt, of course. (I edited #4 a bit.)
I agree with you about the annotate part, but (for example) I'm not clear if there's a cheap and/or fast way to find at what point a comment appeared in Perforce, when it may have been added six release-branch merges back. (I recently started using Mercurial for my personal projects. Night and day.)
There's a somewhat parallel debate about the pros and cons of signing comments.
1. Favor commenting why over how. It may be clear how your function works, but it's rarely self-evident why you chose to use a particular technique -- another will probably seem (perhaps correctly) like a better choice to someone else. Subtleties of design choices and lessons learned from mistakes are much harder to just infer while looking at code than surface details about how it works.
2. If you're about to write a comment, see if better names make it unnecessary, or if breaking a section of a function into a named subfunction clarifies things. (The corollary being that there's nothing keeping you from naming all your stuff "dude" and "heyHeyHey" besides bitter experience and the eternal scorn of your peers.)
3. Consider using asserts, tests, or the type system in place of some comments - they're like comments, but they're actually checked.
4. Consider datestamping any comments more than a few words. (Do it automatically, with an action in your editor.) It only takes a few characters, and sometimes it will be unexpectedly helpful. (A good VC system can help you track down when a given comment was added, of course.)