I do both. Saved me many more times I care to remember.
Sure, name functions and variables in a meaningful way but put a comment block at the top of the function to explain the what, why and how.
Taken further, try this method (it's what I do and often commented upon in a welcomed way):
Like tests, comments are best written before the actual code but they must be reviewed after the code is written to ensure their value.