I used to think commenting code extensively was vital to code readability. I no longer think that is true. There are far better solutions for making code more readable.
When you start practicing Test Driven Design, you start to pay more attention to refactoring. Refactoring is a key activity in TDD because the goal is to pass the test as fast as possible without thinking too much of the elegance of the solution. When the tests pass you refactor. The purpose of the refactoring is to avoid taking huge technical debt so that at any given moment the code is as extensible and readable as possible.
Code commenting does the opposite. It makes the code harder to modify. Comments won't survive the refactoring because you have to remove or edit them to match the new implementation. Then the worst happens and you make a mistake in a comment. This mistake is never caught by the compiler or the runtime. Comments are bound to be incorrect.
While reading about Donald Knuth's literal programming in Coders at work I came to realize how different literal programming and TDD are. In some ways, Literal programming is the opposite of TDD. Knuth describes how he doesn't extract subroutines into real subroutines, but merely comments some parts of bigger subroutines. In TDD we add comments after we've tried to make the code as readable as possible by refactoring. A comment is the last resort to make the code more readable. In literal programming, commenting is the main tool for achieving readability. In TDD we write the test, code and then add a possible comment. In literal programming you explain yourself first with comments, then write the production code. (Knuth didn't even write the code on a computer, instead he wrote the whole program [TeX] on paper first.) Literal programming can increase readability, but it's the arch enemy of refactoring.
Code readability is very important. In fact, it's one of the Rules of Simple Design. How do we increase the readability of our code then, if not by commenting? We use the programming language itself. Modern programming languages like Ruby and Python allow you to write very expressive code. Create small methods, no longer than a few lines and use descriptive names. Use Extract Method on a commented block of code and you're much better off. Additional method calls hardly have any performance impact. I guarantee your bottlenecks are somewhere else.
Certainly there is a place for comments. When should you add a comment? Code that justifies a comment is one that is not tied to the implementation, one that survives trivial refactoring. Such place could be a particularly nasty Regular Expression or a data structure that is an important part of the architecture (such as Domain objects). In general: if you just cannot express your intent with code, consider adding a comment.
