Thursday, March 27, 2008

Commenting Code by Ryan Campbell

Introduction

Commenting your code is like cleaning your bathroom—you never want to do it, but it really does create a more pleasant experience for you and your guests. Because I’ve recently adopted a new mantra to use comments frequently and appropriately in my code, I spent a few hours researching the literature on commenting readability, reusability, and guidelines.


It was a bit overwhelming to see the sheer amount of information and discussions on the topic. Basically, there are a lot of tough, but fundamental questions out there like what does “frequently and appropriately” mean? Because there are a million different beliefs and contradictions on the subject, I created this brief overview to present my findings.

Types of Comments

Code Commenting - This refers to writing descriptive variable names that are self explanatory. This is a minimalist form of commenting, and looks like this:

function addUserToDatabase(userName, userAge)

Without any additional information, you can tell that the function will add a user’s name and age to a database. A common implementation of this is called Hungarian Notation.

Inline Commenting - Specifically, these types of comments come at the end of a line of code, but we can also use this term to refer to comments inside of a function as well. This is the most basic form of commenting.

function calculateHitPoints(cUser) {
var nStrength = document.getElementById("enemyStrength").value; // grab current enemy strength

// subtract user size : small = 1, medium = 2, large = 3
var nDamage = (nStrength * 3) � cUser.nSize;
return cUser.nCurrentHitPoints � nDamage;
}

Function Commenting - This type of commenting is found on the lines above a function, and reveals all of the necessary details about that function. This includes parameters, return values, and any logic quirks or decisions that were made:

/*
* Summary: Calculate hitpoints after attack using formula
* new = current � ((enemyStrength*3) � size)
* Parameters: cUser � object containing hero's stats
* Return: Boolean indicating life or death
*/
function calculateHitPoints(cUser) {

} // end calculateHitPoints

Class / Page Commenting - Comments that refer to an entire page or top level object fall into this category. Usually these comments include a broad overview, last edit date, associated files, author, and contact information. Additionally, this may include a general footer at the bottom of every page. Kevin wrote some great templates for building these types of comments in his feature on using XHTML templates.

/* 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Title :
Author :
URL :

Description :

Created :
Modified :

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/

Commenting Regulars

When developing in a team environment, standardized ways of indicating the next step in the process are great ways of communicating to other programmers and making the entire process efficient. These are also known as functional comments.

[Functional Comments] serve one purpose: adding functionality to the development process.

Bernhard Spuida · The Fine Art of Commenting

They don’t tell you anything about the code, but they do provide documentation on what needs to be done as well as what has been done. Here are some common comments you can feel comfortable using in your code:

  • TODO: This key phrase signifies what needs to be accomplished and should be placed on the line where the future code should go. Some development environments recognize this phrase and will create a to-do list off of it.

  • BUG / FIX: Document a specific bug, or a fix for a bug, and place the comment above the line it pertains to. If you use bug tracking software, include the ID of the bug, so you can always track where it occurred and how you fixed it.

  • TEAMNAME: This comment is usually different wherever you work, but is used to call attention to a certain programmer or programming team. For example, you may want to let the Artificial Intelligence team know why you made a certain decision and so you would use this type of comment to alert them. Read more about this in The Art of Code Documentation by Drew Sikora.

In addition to commenting keywords, there are programs out there that will document your code based on standard comments. While relying on these programs leaves room for error, they are still worth taking a look at. Briefly, two types are XML Comments and JavaDoc

Increasing Comment Readability

In a perfect world, reading code would be like reading a book. Unfortunately, code is written for computers to execute, not for humans to read. You can’t just read code from start to finish—they’re like those choose-your-own-ending books, forcing you to go all over the place to figure out how not to kill your main character. Comments are a great tool for adding context to your code, so that when you jump around you know where you are. With that in mind, here are some tips to make your code easier to read:

Commented Paragraphs � Write your code and comments in paragraph format. In 10 Essential Development Practices, Damian Conway suggests that we should, “Break each piece of code into sequences that achieve a single task.”

Precede comments by a blank line � Doing this creates a distinct separation between your code and comments. Plus, it’s visually pleasing.

Properly tab comments � Make sure comments are tabbed out to the line they are referencing. Additionally, make sure similar comment types align when tabbed. Here’s an example:

var MAX_USERS = 2           //all players
var MAX_POINTS = 100000 //needed to win game

Don’t insult anyone’s intelligence � All commenting is not productive commenting. Too many comments can make your code less meaningful and therefore less readable. An example:

for(i = 0; i < object.length; i++) { //loop until i hits max length

It’s not design � I see a lot of people use crazy characters all over the place and it’s really not necessary. More often than not, it distracts from the business at hand. Keep it simple, keep it sweet.

Create a consistent style � There are many beliefs on the proper way to comment code. Some feel comments should be so detailed that a non programmer could follow the logic, while others believe you use comments for support. What matters most, I think, is that you are consistent in your commenting style. This helps your reader know what to expect when going through several different projects.

Comment while you code - The chances of you commenting a finished project are slim, so do yourself a favor and comment your code immediately.

It is a good practice to write comments at the same time (or earlier than) you write your code.

MSDN · Using Comments Effectively

Commenting while you code forces you to make sure your logic “sounds right.” Plus, your comments are going to be more accurate when the understanding of what’s going on behind-the-scenes is fresh in your mind.

Reusability in Comments

The most interesting concept I came across while reading about code commenting is “comment reusability.” This is something we think about all the time when writing markup and CSS to minimize the amount of work that needs to be done when changes are made. Same principle works wonderfully when it comes to commenting. Here’s an example: Imagine that we have a textbox that’s being edited:

document.getElementById("myTextbox").style.width = "100px"; // change textbox width

The simple comment in that line is not reusable. What if we were to change the textbox to a select element? We would have to change the comment as well. While looking over some coding practices, I came across another question: Is it acceptable to comment the end of a code block, like this:

function calculateHitPoints(cUser) {

} // end calculateHitPoints

I’m split down the middle on this one. With modern text editors that draw lines based on your tabbing, I would not comment the end of every code block. I do, however, see the benefits of commenting the end of a function. Functions usually remain in place, but logic blocks switch around often until bugs are ironed out. Because there are usually a good number of code blocks in a document, the commenting can get pretty heavy without adding a lot of new and useful information.

Speaking of function commenting, Cprogramming.com produced The Hows and Whys of Commenting, which stresses the importance of reusable variable names in functions. They use an example of a funciton that calculates speed. Instead of declaring the function like this:

function getSpeed(runnerDistance, runnerTime)

You should make it reusable by naming the variables generically:

function getSpeed(totalDistance, totalTime)

By doing so, you can logically calculate the distance for any object, such as a plane, car, train, and not just that of a runner.

Now, when it comes to using Hungarian Notation, I want to point out that the topic is a bit controversial, stirring up quite a few heated debates. The Good, The Bad and The Ugly believe it is inefficient to change the variable name every time you change the variable type. For example, ‘szEventType’ should not need to be changed to ‘nEventType’ if you decide to make it an integer rather than a string.

Regardless of you decide to do it, try to remember to take reusability in your comments into consideration. The more reusable the comments, the less time you’re going to spend dealing with them. More importantly, when a team member comes along and makes changes to the code, hopefully, he won’t have to browse through all the comments looking for what to change.

Why Bother?

One of the hardest hurdles in commenting code is convincing yourself to do it, so it is important to look to other sources for motivation.

Prior, clear, and extensive documentation is a key element in creating software that can survive and adapt.

Jef Raskin · Comments Are More Important Than Code.

On a more personal note, after I applied my findings to some of my recent projects, I noticed some significant improvements to my programming lifestyle:

  • I was writing better code. By commenting everything, I was forced to think about why I was doing something rather than just making it work. I was programming smarter rather than harder. Because commenting my code forced me to verbalize my logic and make me think twice about a line of action when putting it into words, I usually found ways to optimize my code when it didn’t “sound right” to me. The comments lead to increased optimization and ultimately less work. Had I gone through after I finished a project to explain things, I’m positive I would have wasted a lot of time reprogramming and recommending bad logic. Time will tell if it decreased bugs as well.

  • I was improving the future. You never know who’s going to be looking at your code or when you’ll need to refer back to it. Future Ryan, my co-workers, potential employers and even my mom are really going to appreciate my commenting investment, because it’s going to save them time. Time is money (especially in programming) and so shaving off time wasted on confusion and interpretation is definitely worth the effort.

  • I was proud of my work. One of my biggest problems I have in my life is working on the same thing day in and day out. If I’m proud of what I doing, it basically removes that mental block. Because my projects were clean, flexible, efficient and sexy, I really enjoyed coming back to them and that, to me, is something priceless. Also, it makes it a lot easier to give a great first impression to job applicants, investors or even obsessive-compulsive blog readers when the code was created in a professional and consistent manner.

See For Yourself

I’ve written a simple JavaScript function to illustrate how even if you think all of the comments seem important, bad commenting decisions can hurt the readability of your code. Here is the result:

//-+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_-
// I wrote this script to process a battle between two units.
// The attack member functions do the calculation, but this
// function determines the order of attacks.
// Two valid objects must be passed in, and then the function
// will return true if everything worked ok.
//-+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_-
function beginBattle(attacker, defender) {
var b; // boolean to hold life or death
var teamCount; // counter for loops
if(defender.agility > attacker.agility) {
b = defender.attack(attacker);
}
// if there was a previous strike, make sure he is still alive then process the attack
if(b) {
b = attacker.attack(defender);
}
// see if any teammates want to counter attack
// loop through the defenders teamates starting at i = 0
for(teamCount = 0; teamCount < defender.team.length; i++) {
var teammate = defender.team[teamCount]; //individual teammate
if(teammate.counterAttack = 1) { // 1 means they have counter attack enabled
b = teammate.attack(attacker);
}
}
// make sure that somewhere in here death processing is handled.
return true;
} // end function

It’s not terrible, but it could be better. Using the exact same function, we’ll apply some of the commenting guidelines I talked about above:

/*
* Summary: Determine order of attacks, and process each battle
* Parameters: Creature object representing attacker | Creature object representing defender
* Return: Boolean indicating successful fight
* Author: Ryan Campbell
*/
function beginBattle(attacker, defender) {
var isAlive; // Boolean inidicating life or death after attack
var teamCount; // Loop counter

// Check for pre-emptive strike
if(defender.agility > attacker.agility) {
isAlive = defender.attack(attacker);
}

// Continue original attack if still alive
if(isAlive) {
isAlive = attacker.attack(defender);
}

// See if any of the defenders teammates wish to counter attack
for(teamCount = 0; teamCount < defender.team.length; i++) {
var teammate = defender.team[teamCount];
if(teammate.counterAttack = 1) {
isAlive = teammate.attack(attacker);
}
}

// TODO: Process the logic that handles attacker or defender deaths

return true;
} // End beginBattle

In my opinion, the code has become much more pleasant to read with only minimal changes. First, we applied some consistency. All of the comments have a blank line above them, start with a capital letter, and are tabbed properly. Next, variables such as ‘b’ were changed to ‘isAlive’ to make them self explanatory. Lastly, a ‘TODO:’ was added to make future changes stand out. By using brief and consistent pieces of language, I’ve significantly improved the readability of my code.

Build Your Own Style

Now, there is an entire movement of programmers out there that believe that code is essentially another form of personal expression and so it’s important for me to stress that I am not suggesting that these ideas and strategies are the only way to explain your code. Instead, I want people to walk away understanding that comments are important because they can affect the readability, performance and professionalism of your programming. I highly recommend that everyone take some time to reflect upon and create commenting guidelines based on what you find is important and necessary for your situation.

If you want to find more information on this topic, I suggest reading all of the articles I’ve linked to throughout this essay. And while I have not read it myself, I have heard many good things about Literate Progamming by Donald E. Knuth. As always, if you have any good ideas about commenting code, let us know because we always like to hear.


Ryan Campbell

Successful Strategies for Commenting Code by Ryan Campbell

This entry was posted 2 years ago and was filed under Features.
You can follow comments on this entry by subscribing to the RSS feed. Comments are currently closed.

1 comment:

Anonymous said...

You write very well.