Monday, April 11, 2016

How do you comment your code?

By Steve Endow

It's one of those overused sayings, like "eat healthy" or "brush and floss regularly", but it's for developers:

"Comment your code."

It even applies to consultants who only occasionally dabble in SQL.  "Comment your code."

Okay, so we've all heard it before, but what does it mean to "comment your code"?

My philosophy around code comments is that they should try to answer the following questions:

1. When
2. By Whom
3. For Whom
4. What
5. Why

For example:

//4/11/2016: S. Endow:  Per Sally Smith, modify the freight calculation routine to include evaluation of dim weight to determine best shipping vendor to reduce shipping fee. Prior calculation didn't consider dim weight, resulting in oversize package fees for new Titan Series products when shipped through certain carriers.

When:  April 11, 2016

By Whom:  Steve Endow

For Whom:  Sally Smith

What:  Changed freight calculation routine

Why:  Old routine didn't consider new product line

So why do I try to cover these 5 points in comments?  After developing Dynamics GP integrations and customizations for the last 10+ years, I've realized that those were the questions that I needed to answer when trying to figure out why an application was behaving a certain way.

3 years after I deploy my code, I simply can't remember why specific changes were made.  After several years, I can look at the code and have no recollection even writing it.  I used to write comments that would answer When, By Whom, and What.  Over time, I learned that For Whom was very important:  "So where did that change come from? Who requested it?".  If I didn't comment that information, the client would think I made that change by my own accord, which is silly, but without a comment, I was unable to tell them who requested the change.

So then I started adding For Whom.  But then I would find comments that would tell me what I changed, and for whom I made the change, but we had no recollection of why we made the change.

Why did we change the overtime calculation to exclude those pay codes?  Why is the code handling company A different from company B?

The Why became one of the most important questions that remained unanswered in my comments.

I still have a hard time remembering to add the Why all of the time.  At the time you make the change, it seems so obvious, so it's very easy to forget to document the Why.  But I've found that "Why" is often the most crucial part of a comment when you have to decipher your code years later.

Given my criteria for code comments, after writing thousands of comment lines, I finally got sick of typing the same thing over and over again:  the date and my name.  So I installed a simple "paste" macro tool that will automatically type out some text when I press a keyboard shortcut.

So I've programmed my Win+C keyboard combination to output my basic comment start:  //4/11/2016: S. Endow:

It seems trivial, but it all adds up, and by using the macro, it makes it that much easier for me to add comments, encouraging me to do so.

So I then had a pretty good practice of adding meaningful, useful, and valuable comments throughout my code.  But what about release notes?  In a Visual Studio solution with thousands of lines of code in numerous classes in multiple projects, where do you put your main, summary, release notes?

At one point, I would put them at the top of my Form Main code.  But that didn't work for console apps.  So for console apps, I put them at the top of Program.cs.  But then what about class libraries that have neither a Main Form nor a Program.cs?  This approach starts to break down quickly.

So I did some searching to see if anyone had a best practice.  After reading a few suggestions on StackOverflow, I settled on Documentation.cs.

Every time I create a solution, I create a Documentation.cs class that just contains my release notes and related release comments.  At first this felt pretty strange.  An empty class with only comments?  Why not a text file or some other type of file?  Well, because a cs file is easy and will always be picked up by source code control.

If I have multiple projects in my solution, my Documentation.cs will be in my Library project.

After using Documentation.cs for a few months, I now love it.  It's very simple and easy and is just something I do without thinking about it.  And I know exactly where to look for release comments and functionality changes.

When I put comments in Documentation.cs, I have no reservations about being verbose.  Lay it all down with as much context and background and detail as possible, because 1, 2, or 3 years later, you'll need every clue you can get to troubleshoot or refactor.

This is an example of the comments I put in my Documentation.cs file.

I start with the date, then list the version of that release, then list every change that I made, sometimes referencing the specific class and method that was changed.

Every time I write code, and every time I comment my code, I'm constantly thinking, "What would an experienced developer think if she saw my code?"  The code I write is just as much my deliverable as my deployment guide or user documentation.  It's the ultimate end product.  Except that very few people other than me actually look at it.

But when you get a call from a customer who suddenly gets an error with the solution that you deployed four years ago, you'll be the one who is scrutinizing that code in far more detail than any customer would.  And you'll appreciate your detailed code comments.

Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Google+ and Twitter


mavrick5 said...

I have been programming for over 30 years and have always commented my code explaining what the code was doing (or trying to do). At one point about 25 years ago while working for McDonnell Douglas, they had a simple set up to comment modifications that I have followed ever since.

Other than the normal name, date, description, etc of what a program does at the top, they had a modification list such as:

Mod Date Who Reason
01 12/11/2016 MAF Changed to fix bug in freight calculation.
02.... etc

Then, in the actual program, you would simply put:

<01 - Start>
some code lines
<01 - End>

if you needed to comment out a line:

<01 - Start>
<01> commented out code
<01 - End>

This way, anyone could follow what changes were being made and why. It also allowed a change to be backed out if necessary. Every time a major release was done, all comment lines would be deleted to clean up the code and start from fresh.

Steve Endow said...

Thanks mavrick5, that's very interesting.

I think that method makes sense, as that is one thing that I have noticed my current commenting and coding lacks: The ability to trace and directly correlate the changes throughout the code to the corresponding release note comments. In my code comments, I do use a date stamp, but not a version number or change number that is directly traceable.

I suspect that some people would counter that technique by saying that the current source code control systems effectively provide similar functionality, as they can easily show you the diffs between each release. So I guess it might be a question of which is simpler, easier, or more efficient depending on the tools, environment, procedures, etc.

I'll give the numbering approach a try and see if it's simpler or easier than trying to do a diff.

As to deleting all comments and starting fresh, that's something I haven't heard of before. I know I would have a hard time with that, as the code comments provide details that I don't document elsewhere, and I think they provide context as I read through code. I suspect in an ideal world (and at defense contractors), there would be change control documentation that would fill the role of my comments, but in the Dynamics GP world where budgets are typically small, I don't usually have the time to re-document every detail of each release.