To paraphrase Philip Wadler, people will talk more about comments than any other aspect of languages. Here's my blather: Toss it on the pile.
Good comments are worth their weight in gold. Most comments are not good. I've coped with code chock full of comments -- but the comments were all repetitions of what the code did. To avoid accusations of putting up a straw man, I'm putting in an example from real code I've had the displeasure of working with:
/* Check the CRC handle allocation */ if(hcrc == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance)); /* Change CRC peripheral state */ hcrc->State = HAL_CRC_STATE_BUSY; /* DeInit the low level hardware */ HAL_CRC_MspDeInit(hcrc); /* Change CRC peripheral state */ hcrc->State = HAL_CRC_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hcrc); /* Return function status */ return HAL_OK;
On the other hand, comments that capture the subtle complexity of
how things interact are incredible time savers. Early Unix had
the infamous /* you are not expected to understand this */
comment.
Out of context, it's been used to poke fun at the inscrutability of Unix.
In context, it's clear that it means "This is not on the exam."
The code around that comment is included below with full context. I'd
consider it an excellent comment:
/* * Switch to stack of the new process and set up * his segmentation registers. */ retu(rp->p_addr); sureg(); /* * If the new process paused because it was * swapped out, set the stack level to the last call * to savu(u_ssav). This means that the return * which is executed immediately after the call to aretu * actually returns from the last routine which did * the savu. * * You are not expected to understand this. */ if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } /* * The value returned here has many subtle implications. * See the newproc comments. */ return(1);
People rarely write this kind of comment. It's difficult to think about why the code is written the way it is and anticipate questions about it.
Even better is another type of comment: The explanation of why an obvious approach was not taken, and how the system is expected to deal with the implications of this. Here's an example:
/* * Cannot use newpath for arbitrary names because the mtpt * array will not be populated correctly. The names #/ and / are * allowed, but other names with / in them draw warnings. */
This comment tells us what alternative was considered, and why it was rejected. Code already explains what it does, though it may need some grubbing about. But it can never tell us what approaches were considered and rejected, and what their flaws were. Re-learning that may require a future reader to experiment and re-derive the problems with code.
Code without comments reads better than code with poor comments. The comments in the first example only serve to drive useful text off the screen. But in clear code, good comments should come rarely: The code should do little that surprises the reader, leaving few subtle points to be explored, and even fewer places where obvious approaches do not suffice.
Finally, parsimony in commenting makes the comments that are there stand out as significant, instead of blending into the noise of things that did not need to be said.