Friday, November 5, 2010

The Art of Commenting Code

When I first started programming I was horrible with comments.  I honestly didn't write them because I didn't see the point.  The reason I did not do it was because I was never forced to maintain any of my code.  In school we often wrote little programs that were a couple hundred lines long that was discarded after each assignment.  Despite my teacher's best efforts it never struck me as to why comments are necessary.  I would comment my code when forced to by my teacher.  This lead to inane commenting like the following:

//Assign 5 to foo
int foo = 5;

If anything my commenting here has hurt the readability of the code because it clutters it with needless information.  If you know the language, you know what an assignment statement looks like, making the comment unnecessary.  It was only once I started working on an J2EE application with approximately 200,000 lines of code that I understood why you comment.  After much thinking about it I've come to the conclusion that you comment to justify the code.  What I mean is if someone reading your code was to ask "Why does this code exist?" the comment should provide the answer.  My comments tend to be long winded compared to most other developers I've encountered, because of this approach.  I often make statements about the origin or the history of a piece of code to give context.  I also believe in making the comment conversational or tell a story.  This makes it both easier to read, more fun to read, and simplifies the communication.  I'll write something like the following:

//The item has to be added to the collection before the call to the next function
//because the control throws an exception if the item is not in the collection
//yet.  It'd be better if we could do it later on but we are limited by the existing
//structure.  If we refactor the control to use WPF we should revisit this.

This of course is completely contrived and doesn't relate to any real code.  I am trying to demonstrate what I believe is a good commenting style. I am doing the following things:
  • I justify the positioning of the code and why it exists there.  
    • This lets a future developer (or which might be me) know why the code is set-up as it is and that the order has a logic to it and what that is
    • It also prevents a developer who is refactoring the code from unwittingly creating an error.  I hate when I move something that appears to have no effect on the logic but then a strange edge case appears that causes an error.  Even worse is when you talk to the original developer and they knew about the error potential but did not document it
  • I also acknowledge any short comings.  
    • This is partly me protecting myself from future developers being to angry at me.  I cannot count the number of times I've read someone's code and just questioned their sanity for coding something in a certain manner.  There might have been logical justification for doing it that way and if I understood that I probably would accept it.  I still may dislike the code but at least I now have context
    • This also provides information to someone who want to improve the code in the future.  At some point in the future someone will be changing that code.  There may be a way to perform the operation in a better manner.  If that person may be less experienced with the code base or less experienced in general they may just assume that this is a good piece of code.
    • It raises a do not copy and paste this flag for people.  Nothing is worse than seeing a poor piece of code copy and pasted.  Inexperienced developers make this mistake often.  They know a piece of code works but they don't understand it.  They therefore copy, paste it, and never examine it closely.  A comment that acknowledges short comings encourages a deeper level of thinking.
  • Provide an upgrade path
    • If there is some point in the future that the code be changed to remove the short comings and I know what that point is I mention it.  I don't necessarily think that those short comings will be removed right away when that upgrade point change occurs but it provides a reference point to make the change.
Its also important to remember that comments are how future developers will be able to understand what the code does and why it does it.  Reading comments is one way you can perform archeology on code to understand it.  You therefore should leave behind artifacts for the future archeologists.  Code  doesn't exist in a vacuum.  We use many other tools like requirements and defect tracking systems to help us manage development.  We stage implementation in to releases.  We have meetings to discuss functionality.  We write using architectures and designs.  All of these are important to the code, but rarely are they referenced in a meaningful way.  Providing well placed linage to the outside materials can provide a wealth of information with the minimal actual writing.

It is impossible to link every piece of code to meaningful external references, but sometimes providing that link is vital.  The easiest link to provide is to requirements management systems and defect tracking systems that give unique identifiers that can be easily referenced.  If a change for a requirement or a defect is fairly esoteric and isolated to a small code section  I will often include the ID of the requirement or the ID in the comments for the code.  Sure, a tool like subversion can be used to gain the same information, but that requires an additional step that most people will not undertake.  It also gives me traceability back to the defect tracking system, which occasionally comes in handy on its own.  Defects and requirements are not the only links that can be put in comments.  If you keep meeting minutes or a record of conversations you can provide a link by putting in the date of the conversation that was the basis for the change.  Architecture and design documents can be referenced in similar manners.  Instead of trying to reexplain in detail why something works the way it does, reference the existing documentation.  If a change significantly changes behavior starting at a certain version number, it doesn't hurt to mention that with that version number the functionality has changed.

You can go overboard with this to the point that it becomes annoying.  Just like the first example of commenting an assignment statement, you don't want to make it so the comments lose meaning.  For example I don't link to a defect number if the defect occurs because of a null reference that is avoided by a simple null check.  Generally, I add the link and level of detail if

  •  The change required significant archeology on my part
  •  If a fix for a defect was non-intuitive
  •  It seems likely that similar changes will need to be made in the future
  • The way something was functioned was specifically prescribed by a meeting or a document
These are not hard and fast rules to follow, but more guidelines.  I do not use the previous list as a checklist.  In fact I had to reverse engineer when I actually do add links to outside information.  It all comes down to a feel for the code and when its useful.  You do not want the linkage to become pedantic, but want to provide others and yourself tools for the future.  After all, you are as likely to be helping yourself as you are to helping others. Numerous times I have had to return to a piece of code I wrote and had to perform archeology on it because I couldn't remember writing it.  We always feel we will remember the code we write.  For the most part that just can't be true because of the sheer volume of code we write.  It will save you time an energy in the long run to write good comments.  Nobody really debates the merits of comments, so I won't continue down that line of thought. I do think the quality of comments is extremely important.  I hope I've given you some thoughts on how to write good comments.

1 comment:

  1. I think another reason to comment code is to add humor to it -- if you can have a developer get a chuckle while reading through your source code, then you are more than simply a programmer, you are a comedian as well.

    Great points all around though -- commenting is definitely something that I have improved drastically on since beginning work on a much larger-scale project than college homework assignments.