“You need to write comments; your code is not self-documenting; good comments are invaluable to understanding your code.”
The other camp says:
“Comments tend to either be redundant information or lies; they create a support burden and are misleading. If you need to comment something, you probably need to refactor that thing instead.”
The second camp is largely correct. The first camp lives in the land of wishful thinking. Sure! Really good comments would be really useful. The problem is, most developers can’t write really good comments and when they do write them, somebody else alters code properties and injects subtle lies into the comments.
Comments create the illusion of understanding. People read the comment and think they know what the code does, when if they read the code, understanding might take longer, but it would be more likely to be understanding, and not misunderstanding. Comments use natural language and even ones that were written by articular developers who understand the code they’re documenting can have ambiguities created by reader inference. Code has a formal logic and can be understood fully by a sufficiently talented reader.
The way to square the circle here is to build verifiable self-documentation into your code. Insist on a high level of unit test code coverage — your unit tests now serve as documentation for your code. Perhaps not really good documentation, but if your developers can’t write good unit test names, and clear tests, you might want to ask yourself how well they were really going to document in comments.
API documentation — especially external API documentation — is of course necessary. But you should build a feedback system into this as well. A single specification file could form the outline of your documentation and also the validator of the input in the actual code. That way, if a given parameter is not added to the documentation, it can’t be used. If it’s marked mandatory in the documentation, it inherently will be mandatory in the API. Etc.
We at Flywheel wrote a set of message classes which guarantees that different components must use the exact same format for a message, that all messages are built in similar ways, and that uses metaprogramming such that the specification of each message is pretty much human-readable documentation (with perhaps ten minutes of explanation beforehand).
Rather than get into the eternal cycle of saying, “Good comments are invaluable” / “Real world comments suck” / “Therefor real world comments are not good comments” / “So the solution is demand something that your employees have a demonstrably difficult time providing,” think like an engineer and develop as many technical fixes to your documentation problem as you can. It will be less effort for more reward.