Comments or Self-Documenting Code?

 < Day Day Up > 



The issue of whether to write comments in your code, and what kind of comments to write, has a tendency to make developers argue with one another. On the one side, you have people who feel that the code should be its own documentation and that comments are superfluous. On the other side are people who think that well-written comments make code easier to read. I personally tend to side with the latter group, with one caveat: Writing good comments is not an excuse to write bad code.

Noise Comments

There are a couple of commenting styles that I don’t care for in source code. I tend to think of these as “noise comments”—comments that make the code longer without really bringing any value to it. The first type of noise comment is the comment that simply repeats the code:

 // DefaultDownloadFolder property  public string DefaultDownloadFolder  {      // Public getter      get      {          // Return the internal variable's value          return _DefaultDownloadFolder;      }      // Public setter      set      {          // Store the supplied value          // in the internal variable          _DefaultDownloadFolder = value;      }  } 

The comments in this code block don’t add anything to the code. Indeed, they’re just a restatement of the code into some sort of stilted English. If someone was absolutely unfamiliar with C#, such comments might help that person to understand what the code is doing. However, it’s safe to assume that most people who will read your source code have a pretty good grasp of the language already and are trying to figure out what your program is doing, not what individual statements are saying.

The other form of noise comment is the formal procedure header:

 // Procedure: GetDownload  // Module: DownloadEngine.cs  // Author: Mike Gunderloy  // Creation Date: 5 November 2003  //  // Inputs:  //    d: A Download variable with information  //       on the file to be downloaded  //  // Outputs:  //    NONE  //  // Revision History:  //    5 Nov 2003: Initial creation  //    8 Nov 2003: Downloading code implemented  //    9 Nov 2003: Added custom exception  //  public void GetDownload(Download d)  {      // Method body goes here  } 

I admit it—I’ve written plenty of formal procedure headers in the past, particularly when I was working as a contract programmer. They’re a great way to make yourself look busy under the guise of adding value to the source code when you can’t figure out how to solve the actual problem. But everything in this comment is purely redundant information:

  • The module name is on the tab at the top of the IDE or in the title bar of your text editor.

  • The procedure name, inputs, and outputs are right there in the source code for anyone to read.

  • The author, creation date, and revision history are all in your source code control system, where they can be easily retrieved when you need them, and where they won’t get in the way when you don’t need them.

If you’re getting paid by the hour and no one is checking your work carefully, write all the noise comments that you want. Of course, such behavior is not the hallmark of a real professional! If the goal is to get your own product to market without wasting time, and to do so with maintainable code, don’t bother.

RULE

Use comments to convey information, not just to repeat information that is stored elsewhere.

Placeholder Comments

Some comments are merely placeholders or notes to your future self:

 // HACK: Brute-force search, can replace if this becomes a perf issue  // TODO: Add code to make sure user has access to folder  // POSTPONE: This is where we'll want to create custom properties 

Visual Studio .NET offers good support for placeholder comments by letting you tie them to the Task List. Select Options from the Tools menu, and then navigate to the Task List section of the Environment options, as shown in Figure 4.3. You can use this section of the Options dialog box to define comment tokens that indicate a task.

click to expand
Figure 4.3: Defining comment tokens

The Task List window, shown in Figure 4.4, will automatically keep itself up-to-date as you add and remove the indicated comments. You can double-click on any task comment to go directly to that comment in your code. This is a handy way to remind yourself to fix things. As a general rule, you shouldn’t be shipping code that still contains UNDONE or TODO tasks.

click to expand
Figure 4.4: The Visual Studio .NET Task List

Summary and Intent Comments

Like assertions and exceptions, comments should have a reason to exist. The noise comments I mentioned earlier fail this simple test, while placeholder comments pass it. Two other types of comments are also useful.

Summary comments are superficially similar to comments that just repeat the code in that they tell you things you could learn by reading the code carefully. For example, here’s a block of the DownloadEngine component with summary comments inserted:

 public void GetDownload(Download d)  {      string filename = string.Empty;      string foldername = string.Empty;      WebClient wc = new WebClient();      try      {          // This method should never be called without          // a Source URL          Debug.Assert(((d.SourceUrl != string.Empty) &&              (d.SourceUrl != null)),              "Empty SourceUrl",              "Can't download a file unless a Source URL is supplied");          // If no filename specified, derive from SourceUrl          if((d.FileName == string.Empty) || (d.FileName == null))          {              filename = Path.GetFileName(d.SourceUrl);          }          else          {              filename = d.FileName;          }          // If no download folder specified, use default          if((d.DownloadFolder == string.Empty) ||              (d.DownloadFolder == null))          {              foldername = DefaultDownloadFolder;          }          else          {              foldername = d.DownloadFolder;          }          // Ensure that we got a folder name somehow          Debug.Assert(foldername != string.Empty,              "Empty foldername",              "Download folder not set and no default supplied");          // Use WebClient to do the download          wc.DownloadFile(d.SourceUrl, Path.Combine(foldername, filename));          // UNDONE: set file size in the Download object      }      catch (Exception e)      {          // Bubble any exception up to caller, with custom info          throw new DownloadException("Unable to download" ,d, e);      }      finally      {          wc.Dispose();      }  } 

In this case, the comments don’t add anything that a good programmer couldn’t figure out by reading the code. But they’re still useful, simply because the comments are shorter than the code. With the default color-coding in Visual Studio .NET, you can skim for green text to easily read just the comments. Such summary comments give you a faster way to grasp what a procedure is doing without having to read every single line of code.

Tip

Some programmer’s editors offer a “collapse to comments” feature that can hide all of the source code in a procedure and show you just the comments. Alas, Visual Studio .NET doesn’t have this capability.

Even better than summary comments are intent comments. Intent comments are the hardest type to write, but they’re often the most useful. With intent comments, instead of explaining how the code works, you explain why it’s there in the first place. An intent comment for the GetDownload method might look like this:

 // GetDownload uses the information in a Download object  // to get the specified file from the Internet to a local  // hard drive. Any download errors are wrapped in a  // custom exception and returned to the caller, along with  // the failing Download object. 

Intent comments are great when you need to maintain code, especially code that you’ve been away from for a long time (defined as any more than a few days). By skimming the intent comments, you can quickly locate the section of the code that you need to work on.

TECHNOLOGY TRAP: When Good Comments Go Bad

start example

There’s one major problem with writing good comments: They’re not tightly coupled to the code that you’re commenting on. What this means is that comments and code can (and do) drift out of synchronization. If you dive into the code for a quick fix to respond to a problem that just turned up in the debugger, you may forget to review the comments and fix them as well.

People who focus on this problem tend to be in the “self-documenting code” category. If the comments are going to drift away from the code, and the code itself is definitive, why bother with comments in the first place? Just write understandable code and be done with it.

I’m sympathetic to this point of view, but I don’t agree with it. The basic mistake here, I think, is to view comments as just a restatement of the code. For noise comments, that’s true. But if you’re writing good summary or intent comments, there’s more to the comments than just restating the code in English. Comments offer a more efficient way to get to the part of the code you want, just as an index helps you find the page in a book that you want to read. A “self-documenting book” wouldn’t need an index; you just read the book to find the page you want. But most of us would agree that the index adds efficiency in some situations.

The real cure for the comment synchronization problem is to exercise some discipline. When you change code, make sure the comments are still sensible, and change the comments if they need to be resynchronized with the code. You’ll also find that this is less of a problem if you concentrate on writing a few good intent comments. Most bug fixes change the implementation of code, but not its intent.

Another approach to keeping code and comments synchronized is to use literate programming, in which special tools let you write documentation and code together, separating them out for printing and compiling. In this approach, a program is considered a work of literature rather than source code to be commented on separately. You can find more information at the Literate Programming website (www.literateprogramming.com/). I’m not aware of any literate programming tools specifically targeted at C#, but the LEO text editor (http://personalpages.tds.net/~edream/front.html) lets you experiment with literate approaches in any source code language.

end example



 < Day Day Up > 



Coder to Developer. Tools and Strategies for Delivering Your Software
Coder to Developer: Tools and Strategies for Delivering Your Software
ISBN: 078214327X
EAN: 2147483647
Year: 2003
Pages: 118

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net