The Robert C. Martin quote is taken out of context. Here is the quote with a bit more context:
Nothing can be quite so helpful as a well-placed comment. Nothing can
clutter up a module more than frivolous dogmatic comments. Nothing
can be quite so damaging as an old crufty comment that propagates lies
Comments are not like Schindler's List. They are not "pure good."
Indeed, comments are, at best, a necessary evil. If our programming
languages were expressive enough, or if we had the talent to subtly
wield those languages to express our intent, we would not need
comments very much -- perhaps not at all.
The proper use of comments is to compensate for our failure to express
ourself in code. Note that I used the word failure. I meant it.
Comments are always failures. We must have them because we cannot
always figure out how to express ourselves without them, but their use
is not a cause for celebration.
So when you find yourself in a position where you need to write a
comment, think it through and see whether there isn't some way to turn
the tables and express yourself in code. Every time you express
yourself in code, you should pat yourself on the back. Every time you
write a comment, you should grimace and feel the failure of your
ability of expression.
(Copied from here, but the original quote is from Clean Code: A Handbook of Agile Software Craftsmanship)
How this quote is reduced into "Comments are always failures" is a good example of how some people will take a sensible quote out of context and turning it into stupid dogma.
API documentation (like javadoc) is supposed to document the API so the user can use it without having to read the source code. So in this case the documentation should explain what the method does. Now you can argue that "Retrieves a product by its id" is redundant because it is already indicated by the method name, but the information that
null may be returned is definitely important to document, since this in not in any way obvious.
If you want to avoid the necessity of the comment, you have to remove the underlying problem (which is the use of
null as a valid return value), by making the API more explicit. For example you could return some kind of
Option<Product> type, so the type signature itself communicates clearly what will be returned in case the product is not found.
But in any case it is not realistic to document an API fully just through method names and type signatures. Use doc-comments for any additional non-obvious information which the user should know. Take say the API documentation from
DateTime.AddMonths() in the BCL:
The AddMonths method calculates the resulting month and year, taking
into account leap years and the number of days in a month, then
adjusts the day part of the resulting DateTime object. If the
resulting day is not a valid day in the resulting month, the last
valid day of the resulting month is used. For example, March 31st + 1
month = April 30th. The time-of-day part of the resulting DateTime
object remains the same as this instance.
There is no way you could express this using just the method name and signature! Of course your class documentation might not require this level of detail, it is just an example.
Inline comments are not bad either.
Bad comments are bad. For example comments which only explains what can be trivially seen from the code, the classical example being:
// increment x by one
Comments which explains something which could be made clear by renaming a variable or method or otherwise restructuring the code, is a code smell:
// data1 is the collection of tasks which failed during execution
var data1 = getData1();
These are the kind of comments Martin rails against. The comment is a symptom of a failure to write clear code - in this case to use self-explanatory names for variables and methods. The comment itself is of course not the problem, the problem is we need the comment to understand the code.
But comments should be used to explain everything which is not obvious from the code, e.g. why the code is written a certain non-obvious way:
// need to reset foo before calling bar due to a bug in the foo component.
Comments which explains what an overly convoluted piece of code does is also a smell, but the fix is not to outlaw comments, the fix is the fix the code! In the real word, convoluted code does happen (hopefully only temporarily until a refactor) but no ordinary developer writes perfect clean code the first time. When convoluted code happens it is much better to write a comment explaining what it does than not write a comment. This comment will also make it easier to refactor later.
Sometimes code is unavoidably complex. It may be an complicated algorithm, or it may be code sacrificing clarity for performance reasons. Again comments are necessary.