What is self-documenting code and can it replace well documented code?

In my opinion, any code should be self-documenting. In good, self-documented code, you don't have to explain every single line because every identifier (variable, method, class) has a clear semantic name. Having more comments than necessary actually makes it harder (!) to read the code, so if your colleague

  • writes documentation comments (Doxygen, JavaDoc, XML comments etc.) for every class, member, type and method AND
  • clearly comments any parts of the code that are not self-documenting AND
  • writes a comment for each block of code that explains the intent, or what the code does on a higher abstraction level (i.e. find all files larger than 10 MB instead of loop through all files in a directory, test if file size is larger than 10 MB, yield return if true)

his code and documentation is fine, in my opinion. Note that self-documented code does not mean that there should be no comments, but only that there should be no unnecessary comments. The thing is, however, that by reading the code (including comments and documentation comments) should yield an immediate understanding of what the code does and why. If the "self-documenting" code takes longer to understand than commented code, it is not really self-documenting.


Well, since this is about comments and code, let's look at some actual code. Compare this typical code:

float a, b, c; a=9.81; b=5; c= .5*a*(b^2);

To this self-documenting code, which shows what is being done:

const float gravitationalForce = 9.81;
float timeInSeconds = 5;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);

And then to this documented code, which better explains why it is being done:

/* compute displacement with Newton's equation x = vₒt + ½at² */
const float gravitationalForce = 9.81;
float timeInSeconds = 5;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);

And the final version of code as documentation with zero comments needed:

float computeDisplacement(float timeInSeconds) {
    const float gravitationalForce = 9.81;
    float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);
    return displacement;
}

Here's an example of a poor commenting style:

const float a = 9.81; //gravitational force
float b = 5; //time in seconds
float c = (1/2)*a*(b^2) //multiply the time and gravity together to get displacement.

In the last example, comments are used when variables should have been descriptively named instead, and the results of an operation are summarized when we can clearly see what the operation is. I would prefer the self-documented second example to this any day, and perhaps that is what your friend is talking about when he says self-documented code.

I would say that it depends on the context of what you are doing. To me, the self-documented code is probably sufficient in this case, but a comment detailing the methodology behind what is behind done (in this example, the equation) is also useful.