Taken from my reply to a post regarding the topic on Facebook, a few words introducing key guidelines I follow when commenting my code.
Regarding classes, I like to provide a class summary stating the intent and purpose. Accessors, Mutators, Constructors – I don’t feel the need to comment them as their roles are (and should be) rather self-explanatory. Non boiler-plate methods, however, receive a similar, but more succinct, documentation, perhaps with some implementation context if needed (Interface and Abstract Class implementation.
I comment Interfaces in a much similar way to Classes, with focus on the intent of the responsibility that the interface is capturing as well as hints on how to best use it.
As for inline commenting, I try to keep it to a minimal, used sparingly for algorithms, complex blocks, etc. Arguably, if implementation description is needed for complex blocks, it is likely that your method needs to be refined and abstracted further.
All in all, a program should really only be commented as much as they need be, and no more – it becomes rather silly when more /* blah blah */ than code is found in a source file. What is greatly undervalued is the intuitiveness of good code through naming conventions and clear intent of what is being done. I’m a proponent of good code reading like a story; easy to comprehend and with clear purpose.
On topic, I found this book to be very insightful: Clean Code: A Handbook of Agile Software Craftmanship and recommend it to all aspiring developers. You too may find it as insightful as I have.