I'm not sure there are many cases where there should be long amounts of expressive code.
If you're doing something obvious, you should generally be able to program it concisely, in which case you have a high comment-to-code ratio because the amount of code is low. Sometimes this will be because you're importing an external library to do something, or because you're calling out to an internal library. Sometimes this will be because you found a straightforward implementation. If you're finding yourself writing hundreds of lines of code to do a single obvious task then chances are high you're implementing it poorly (and, specifically, in a way where your defect rate is likely proportional to the number of lines of code).
And if you're doing several obvious things, then the point of the code is not to explain what the code is doing, but why it's doing that. What is the business purpose of the code? Which customer cares about this edge case that you're handling, and under what circumstances can you stop handling it? Why did you decide that the common library wouldn't actually work here? If you're converting data from an awful legacy format, why are your ingesters / parsers for the legacy format designed in this way? If you're micro-optimizing for performance, why are the optimizations sound (i.e., why do they accomplish the same thing as the unoptimized version), how do they work, and why did you decide these spots need to be optimized? Each individual thing you do might be obvious on its own, but the arrangement of the whole thing needs comments for each step, which again gives you a high comment-to-code ratio.
I might have misused the word expressive, I don't mean bloated code with more than necessary logic.
I just meant simple to understand variable, function, and class names. That combined with small classes and functions, makes following the logic of your program extremely easy.
Following concepts like DRY (don't repeat yourself) and the single responsibility principle ensure that you're making more easily testable code, and I'm sure less overall LOC.
While your fundamental point is very valid, there are plenty of times where a comment to flag up a fine point of your clean and precise code will save future-you hours of head-scratching.
I absolutely do not comment enough, but knowing this, I try to stick to the principle that if I have had to stop and think through an expression before I write it, then I am likely to eventually thank myself for leaving a short explanatory note.
And moreover, it may not be me scratching my head over that nest of ternaries in a year's time - it may be some other poor soul. And while that poor soul won't thank me for leaving a comment, he or she will certainly curse my name - quite possibly vocally and publicly - for not leaving one.
Well, let's consider an example from this very code:
// The binding is two-step process. PV.Spec.ClaimRef is modified first and
// PVC.Spec.VolumeName second. At any point of this transaction, the PV or PVC
// can be modified by user or other controller or completely deleted. Also,
// two (or more) controllers may try to bind different volumes to different
// claims at the same time. The controller must recover from any conflicts
// that may arise from these conditions.
How would you rewrite the code so that this information was explicit in the code alone, and as obvious as when it is stated in these comments? Note that simply being able to handle any conflicts that may arise from these conditions is not necessarily the same as saying that they can occur and must be handled, as any particular implementation is invariably an over-specification.
As for redundant comments explaining the obvious, that seems to be something of a straw man, at least in my experience - personally, I have very rarely seen such code. The person who is not motivated to write useful comments apparently prefers to write no comments rather than useless ones.
My comment was directed to the OP's question of comment:code ratio in general, not in this exact circumstance.
Additionally, in no way am I advocating for no comments, that's obviously not possible (like your example). Comments are useful, even necessary, for code that might have an otherwise confusing logic to them.
I've seen plenty of code with documentation for a method with nothing more than:
/**
* Bills the user
*
* @param user The user to bill
*/
public void billUser(User user) {
//
}
In my opinion, that comment is completely redundant, and I think it's driven by the idea that we should comment EVERYTHING.
Though there should definitely be documentation here. What happens if `user` is null? What if the user doesn't have enough balance for the transaction to complete? What if the transaction fails?
I see this as someone trying to fool a linter that demands they have documentation. I think it's better to say "comment everything" because it puts documentation as a first-class consideration rather than an afterthought.
If it is a general principle, then would one not expect it to apply in this case? More importantly, this is not a corner case; situations where there are specific conventions and protocols that have to be handled consistently in various cases are extremely common in software. It is also not uncommon to see optimized code that is much easier to understand when it is explained as a modification of a simpler implementation.
With regard to the sample, then if that is your experience, I cannot deny it, but, irritating as it may be, it seems fairly harmless. It appears to date from a time when it was thought that extremely prescriptive coding style standards was the way to fix programming - an even less realistic belief than the idea that code can be entirely self-documenting.
Code shows how something happens (i.e., a string comes into a function and is parsed and only the date from it is returned), but it's so bad at showing WHY something needs to happen. My comments are almost always about why I'm doing it in the way I am, complete with examples of test cases where the users broke things in ways I wasn't originally expecting. Ten years from now, the code part will be rewritten using whatever crazy new stuff the language supports, but the underlying need for doing it at all will probably still be around.
As a counter example, here is a C file of 20,000 lines and no comments. I pushed this to Github long time ago, as it was the most gigantic "real" C file I have encountered.
Comments are very barebone. There is structure, but needing to mess with this kind of code would be scary. Granted, most games are write once and never look back.
You made a good point because this code is neither clean nor expressive. The parent comment talked about clean and expressive code. Can you show some of clean and expressive code and try to make the same argument again? (I am not holding my breath that you will)
If you're doing something obvious, you should generally be able to program it concisely, in which case you have a high comment-to-code ratio because the amount of code is low. Sometimes this will be because you're importing an external library to do something, or because you're calling out to an internal library. Sometimes this will be because you found a straightforward implementation. If you're finding yourself writing hundreds of lines of code to do a single obvious task then chances are high you're implementing it poorly (and, specifically, in a way where your defect rate is likely proportional to the number of lines of code).
And if you're doing several obvious things, then the point of the code is not to explain what the code is doing, but why it's doing that. What is the business purpose of the code? Which customer cares about this edge case that you're handling, and under what circumstances can you stop handling it? Why did you decide that the common library wouldn't actually work here? If you're converting data from an awful legacy format, why are your ingesters / parsers for the legacy format designed in this way? If you're micro-optimizing for performance, why are the optimizations sound (i.e., why do they accomplish the same thing as the unoptimized version), how do they work, and why did you decide these spots need to be optimized? Each individual thing you do might be obvious on its own, but the arrangement of the whole thing needs comments for each step, which again gives you a high comment-to-code ratio.