I’ve recently come across a lot of posts that proclaim that commenting your code is bad practice.
I think the problem here is the same problem most arguments, on any topic, have. There are two sides that basically see the argument as black and white. Either comments are good and should be used everywhere, or comments are bad and should never be used. To abuse a cliché “No problem is black and white, there are always shades of grey.”
Let’s look at some of the (strawman) arguments.
Comments get out-of-sync with the code.
The typical example of comments getting out-of-sync is as follows…
## Always returns true. def isAvailable(): return False
Anti-commenters propose that descriptive naming is the solution to this problem. However they usually fail to take into account that any developer that would change the code and not the comment, would also likely change the code and not the descriptive name. Here’s what the descriptive name solution would look like after it was modified like the above…
def returnTrue(): return False
Please enlighten me, how is this any better? I wholeheartedly agree that we should use good descriptive names. However this isn’t a silver bullet that will magically fix all problems introduced by lazy or apathetic programmers. My question to the anti-commenters; if a developer is not capable of writing or maintaining good comments, what makes you think they are capable of choosing and updating good names?
I often read that long functions should be refactored into a number of smaller functions. It would seem that the criteria for creating a new function is dependent on the length of the code. For instance, this piece of code is similar to what you usually see in articles about extracting methods…
def printAmountOwed(name, amount): printBanner() ## Print details of amount owed print "Name:", name print "Amount Owed:", amount
First off, the comment here is strictly unnecessary and is a good example of how not to comment, but that’s not the point here. The idea is that, wherever you would put a comment it is a good place to extract a method. Those that (IMHO) take this practice to the extreme would prefer this code…
def printAmountOwed(name, amount): printBanner() printDetails(name, amount) def printDetails(name, amount): print "Name:", name print "Amount Owed:", amount
There are a few problems that I see with this. First it introduces the overhead of a function call, which is unnecessary in my opinion. Second, this code is of insufficient complexity to justify having to chase down the definition of printDetails. I would much prefer to read and write a few print statements. In my opinion this does not reduce the complexity or the clarity of the code, it increases it.
Maybe I’m missing something, but that’s not how I see the purpose of refactoring. When I refactor code I don’t arbitrarily break out larger functions into smaller functions that are only ever called once. Instead, I look for patterns that are repeated across the code base and try to create new functions that encapsulate those patterns.
Sure breaking every function into smaller functions enhances the possibility of being able to reuse that code later. However this seems to violate the principle of you ain’t gonna need it. Personally, I try not to build a bridge when what I really need is a plank. When I find myself thinking, “I’m pretty sure I’ve done this before…”, I know it’s time to look for a way to refactor my code.
Steve Yegge wrote a pretty good article on commenting and code density which illustrates an important point. Your experience dictates your disposition towards comments. I won’t rehash the article here, I encourage you to read it yourself, however this sheds some light on why this argument can get so heated. On the one hand you have experienced developers who are accustom to reading and writing dense code and on the other you have new programmers, trying to make sense of all the complexity, that need to “tell a story about the code” to help them understand it.
There is no good argument for writing code to the lowest common denominator. However there is a pretty good argument for realizing that you are part of a team (or lineage) of programmers that will work on said code. If you don’t make some allowances for the less skilled, eventually your beautifully crafted code will be completely rewritten by someone with less experience just because they didn’t understand it. I don’t know about you, but I do not enjoy working hard on something just to have it redone in an inferior way.
*Disclaimer: I am in no way asserting that I have the perfect system or that I never write bad code/comments. I don’t think anyone can accurately claim that they never make mistakes or that they have a perfect and infallible system.