It is all about how human mind works. We let things go smoothly when it fits our expectation. When things start to fit out expectations in a row, we even kick into an auto-pilot mode where we spend almost no effort at all.
However, out mind gets alerted when sense inconsistency from our expectations. When that happens, our train of thoughts slows down or even halts, and we have to figure out the inconsistency, develop new understanding and build up new sets of expectations. Afterwards, we will continue, but always start slow, and only accelerates when our expectation fits what we receive for a couple consecutive episodes.
When we read some code, we always need to build up some expectations first -- that is to figure out what the code is supposed to do. If there is no comments, we will simply trying to figure that out from the code directly. If there is such comment exist that explains what the code is supposed to do, we will read it; but then we don't simply cruise along the code, we always read the code and check whether it is consistent against what we expect from reading the comments. Only after we confirmed such consistency for a few segments then we start to cruise along -- read briskly or even omit chunks of code.
As current practice, we do not just comment on the overall picture of what want to do (in code), we comment on codes that are difficult to read. Because the code is difficult to read, we will still have difficult time when we trying to confirm the consistency (between the comment and code, ultimately between what the code in literal and in our expectation). As this process is slow, we hardly ever get to the stage of crusing.
And because the code is difficult, even the original coder is having trouble maintain the consistency and often write comments that is inconsistent to the code. We all do that. After all, or bugs are simply inconsitency between what we think the code is doing and what the code is actually doing. On reading such code (with comments inconsistent against the code), we do not just slow down, we have to halt until we figure out which to accept. As we are not the original author or have completely forgotten, this in the end become a guesswork.
I am not suggesting that reading such code without comments are easy, but comments simply adds onto the input load and as well as the extra demand of consistency check. That is the harm of most comments.
Of course, the root problem is that code is difficult to read, which is what literal programming and MyDef is trying to address.
PS: I am aware there are a school of programmers who likes commented code. I believe they simply skip the code and only read the comment and then trust the code do what the comments say. That will work if the comments are writen as text books. Comments are often insufficient as is.
PS2: This is how code without comments can work. Codes are often simple construction units: if-switches and for-loops. We understand them on the unit level intuitively. Then these constuction units form common patterns, which our brain also can assimilate into familiar expectations. When the code are only made of simple, familar patterns, our brains spends no effort at all reading them -- I believe I am simply explaining how experience work. Then at higher logic level, it is hard no matter what. If the code is factored well with routine/block names reflect semantic expectation, then it is no harder to read the code than to read the documentation.