The Short, Better, and Correct Answer
The idea that well-written, "self-documented code" is all you need is an anti-pattern and should die, even when it makes exceptions for comments that explain "why". It's a myth that you can always write all code for any algorithm clear enough for any programmer to glance at and get it (or that it won't require refactoring or organizational time you don't have). Even more importantly, more often than not, programmers who think they write clear code do not.
A much better answer than comments should only be used to explain "why" is that comments should:
- explain "why" (of course)
- explain "what" on individual lines only when the code is complex or the purpose is unclear and it can't be or isn't worth simplifying further
- explain "what" for blocks of code to speed up comprehension and locating what you need
The Explanation to Back It Up
People erroneously think the only reason people use comments is to explain what a line of code means. The truth is a large purpose of commenting code is to make it quicker to glance through your code and find what you're looking for. When I come back to code later or read someone else's code, sure, I can read and understand a section of well written code - but isn't it faster and easier to read the comment at the top saying what that section of code does and skip it altogether if it's not what I'm looking for? Why sit there and figure out code at all, even if it's well written, if you can glance at a couple comments and understand an entire function? That's why we use descriptive names for functions - no one says I don't need to use a descriptive name for my function because someone can just look through my cleanly written code to see what it does.
For example, if I'm looking through someone else's function, is it easier to go line by line through the code to see what it's doing or to glance at three well written comments throughout the function to see exactly what the function is doing and where it's doing it?
Another anti-pattern is to use functions to comment your code. Why is overusing functions any better than overusing comments? If a section of code is not going to be reused, it shouldn't be put in a function, especially just to avoid commenting a section of code. That's what code folding is for. Using functions like that is the same as embracing GOTO statements - it creates spaghetti code that can be a pain to follow.
Essentially, when you work in an enterprise environment, where people are constantly sharing code and people don't always have the time to make their code perfect, a few good comments can save tons of time and frustration. And remember, while you may be a guru who can read through code at light speed, not everyone in your office probably is.