If you have to write a comment that isn't at the head of a function, the code block might need to get refactored. Every new line of comments increases this probability. Don't comment bad code. Rewrite it.

Inline comments can be a sign that the code is over-engineered, unnecessarily complex, or over/under abstracted. Instead, follow this.

Avoid describing the how. The how should be obvious from the code.
Instead, describe what your code does at the beginning of the function. And in some cases, why.

We tend to like inline comments to describe the how of a clever piece of code. Clever code is rarely maintainable, and often simply wrong. Other times, we decide that documentation should live right next to the code. Maybe that's appropriate, but chances are that it would be most accessible (and indexable) in a knowledge management system or a readme.

Comments are more susceptible to bit rot than any other code. They aren't tested, and there are no compile or runtime checks to make sure they are correct. Adding TODOs or references to a bug tracker or issue can be OK if you have the right tools in place and consistent form. Otherwise, they quickly become forgotten, dead links, or wrong!

Code can be self-documenting through minimizing control flow, picking explanatory variable names, and packaging it logically (e.g., through modules, files, and functions).

Functions, methods, and classes should always be documented with comments at the start of their block. This not only gives important contextual information, but also is used by automated systems like intellisense and search in the IDE. But be a little more careful next time you break out the inline comments.

This was #11 / 31 on my post, Reflections on 10,000 Hours of Programming.