I have always hated this. I feel in a lot of cases it's just a regurgitated concept that is spouted by developers who just latched on to something they can say to sound smart. In which they have never thought critically about it, and have just used it as a justification for them to not have to put in the effort to do quality work.

The TL;DR; Do document your design by stating the method/function/classes purpose, state your inputs, state your return states. Try to be consistent. Avoid creating ambiguous states, where your co-workers or future developers have to guess what is correct when they use your code.

My opinion is that methods/functions/classes should have documentation stating their purpose and design. Many languages have built in documentation generators or are supported by external generator projects like Doxygen.

Above your method/function/class just put the syntax for your documentation engine. state what your thing does. state the input parameters, state the returns (which includes documenting the success states, and the error states). Bonus points for having a usage example on how correctly use the method/function/class.

just doing this I feel is the bare minimum for future developers to be able to pick up from where you left off. It is like declaring an outline just like writing an english paper. State the purpose for your code.

Now as far as the code itself; Yes by all means write clean and self documenting code. You do not need inline comments as a general rule. However, sometimes you have requirements from a customer and there is complex business logic. Having documentation in the code of an algorithm or business steps can be very helpful.

Complete lack of comments on return states can cause future bugs. A example is a recent project in which I took over for a customer for their websites web service back end, does not have any comments. There are bugs and errors, since my predecessors did not document return states it is hard to tell what the effect of a fix will be. In one particular case, there is a null reference where the variable has check before use, which is used to populate later data. This particular method returns a array of object. The grey area here is what should be returning in the failure state.

What do we return to fix the overall error?

A null Array of objects?

A instantiated but empty object with null components?

A instantiated array object that is empty but containing no nulls (nulls fixed to zero length strings or zero)?

A instantiated array object with the data populated for what we do have and nulls for what we don't have?

A instantiated array object with the data populated for what we do have and no nulls, empty strings and zero's?

As the code is currently, we can not answer this question because each return case is technically correct. Looking at the references upstream we see the method in question being used differently, some cases there checking for a null return, some there checking null components, some checking for empty strings or zero, etc...

This mess, all stems from the original developer not defining or stating the success states and failures on the returns and the example usage in the codes documentation. what is worse is that in other area's of the code the same developers are doing similar logic, but employing yet another return scheme. What is worse than all of that, the method in question, is being used by the same developer (that they wrote) with different return checks. (I guess they slept since then... forgetting how their own code works).

The point is that it is unclear. Looking at the code, yes it is self documenting, fairly clean code, and not written poorly when you just focus on individual chunks. However as a whole the code is not consistent, has lots of guess work/assumptions made which makes for lots of bugs.

This project has been a total refactor, clean up job, in which the my client is happy for the better results, but is feeling the pain of previous less than quality work done by the "popular" in town development house.