16 September 2011

Write Better Comments by Tomorrow Morning

I've spent some time recently trying to improve my code comments.  Most of us just write comments without much thought and carry on with the task at hand, however after a couple of weeks of iterative improvement I have some really simple tips that will make you write better comments tomorrow.

Tip 1: Delete Bad Comments

If you're working on a large code base, you'll invariably find some comment that's questionable, but sometimes you'll find comments that are even worse, and those comments simply need to go.  To me, the two kinds of comments that fit in this category are:

  1. Machine generated comments: These tend to be blatant and useless.  "The getFoo method gets Foo." or "The isNotEnabled method returns the value of notEnabled.".  If you're using Eclipse, the shortcut Ctrl-D can be used to delete a line and these comments are ripe for the killing.
  2. Lies: Over time code is refactored, shaped, copy-pasted, "fixed", outsourced, insourced, sold, bought until it eventually winds up in front of you.  During all this ebb and flow, some comments don't keep up with the code.  If the method signature you're looking at is "public List obtainShipments(Locale locale, Country country);" and the comment is "This method will return true if the system can ship to the given country." then you know it's wrong.   If this is not code you're currently cleaning up, then delete it.  
Wait, this sounds harsh.  You should spend the time to rewrite it as a proper comment, right?  Wrong, and here's why.

If you've been a developer for a while, you know the feeling of being "in the zone".  That time where the entire system you're working on is in your head and you can think of side-effects and how everything works.  You're one with the matrix. If you're not working on the methods with the generated comments and lies, then you're not going to add any value trying to write comments and it's going to pull you out of the zone; so don't.

Also, the comments that you see there will leave you (and others) with the feeling that comments are there to help you.  You've probably scanned a class before and thought "Uh-oh, there's almost no comments here, this could be tricky."  With the above two types of comments in that class it gives you a false sense of security.  You've got source control.  Bad comments are worse than no comments, delete them and move on.

Tip 2:  Explain the WTF's

Sometimes the code you're working on has something weird and counter-intuitive about it.  Things that you totally understand, but others may not.  Usually they're the result of bugs or missing features elsewhere in the system.  When you're writing code that works around a bug, go find the issue # in that project's issue tracker and add the full URL in a comment.  Also explain what you would rather the code do if the bug weren't there.  If there isn't an existing bug then file one.  You may discover you misunderstood some functionality or that it's fixed in a newer version.  

If you can't upgrade the library you depend on, mention that the bug is fixed in a newer version in your comment. Also, if you use a dependency management system like Maven or Ivy, add a comment near the dependency "Version 2.1.2 will fix BUG-7509 and then we can remove the workaround in SuperFancyImpl". This tiny investment of time will help the next developer who looks at the code.

Tip 3:  Describe Relationships

More than the other two tips, this tip takes your comments to the next level.

A developer will stumble across your code, following data flow.  They'll want to know why your code is here and how it interacts with other code, so tell them!

Lets imagine a restaurant simulator.   As a developer you find the "Table" class.  Comments like "A table in a restaurant." or "An implementation of a Table." are good Ctrl-D candidates.  Instead, here's something a little better:
"Tables represent a location in a restaurant where customers are served food.  Restaurant Customers attach themselves to a Table which is then served by a number of TableWorkers including the Server Employee and TableCleaner.  It is often allocated by the Reservation system, check CustomerSeater for how Customers are seated.  Constructed Tables usually come from the TableFactory and are always added to the RestaurantBuilding."
Let's take a look at the recipe this comment follows:
  1. Who Am I: If this class represents a business object or business activity, then copy and paste the description from any documentation or planning sessions you've had.  If there isn't any, then write a note to yourself about why you decided you wanted to make a new class.
  2. My Close Family: This class describes very simply how it interacts with other classes around it, either in the same package or members that would reference it.
  3. Bend Encapsulation: In the comment we mention TableCleaner as an implementation of TableWorker.  Chances are the Table class doesn't have any code reference to TableCleaner, but our comment does.  This can be an "Aha!" moment for a developer.  Eclipse is smart enough to dig around in comments when you're refactoring so it's not as dangerous as you might think.
  4. Use "usually" and "often": Should Table know that it comes from a TableFactory? No.  Should a developer know this? Absolutely.  By saying "usually", we hint to the developer that this is probably the common case, but because of the separation we can't say definitively this will be true.
The last two ingredients are what makes this comment a cut above the rest. It helps guide me up and beyond what most other comments would help me with.

What If I Have To Have Comments?

You might wondering what to do if you have a tool that enforces comments in your system and will fail your CI build if you start getting Ctrl-D happy.  It's pretty simple, disable the rules that force you to write comments.  

At my work place we have rules that all methods must have comments, and comments must end with a period for proper grammar.  Want to know what comment I've seen more times than I'd like to admit?

 /**
  * .
    * @return boolean .
    */

Yup.  The problem with enforcing comments is you're enforcing their existence, not their content and simply having a comment isn't ever going to be enough.  The code metric tools don't enforce quality, just quantity.  So ask people around you if it's more important to have lots of comments or if it's important to have better comments.  Maybe for your workplace, quantity is better...
 
That's It!

I'm still experimenting with other techniques, but so far these have had a great impact in my development. Other tips and ideas are welcome!

No comments: