Coding Without Comments

It’s OK to end up with comments in your code, but never, ever start with comments. - I guess this line was edited out? Cos I can’t find it in the article. Good thing too.

Comments are great. Take another step.

Use GhostDoc to automatically generate comments for methods (a short description with parameters, if your function has a good name, also the comment is quite good too). What do you do with this comments?

Next Step: Use Ndoc to create an html Helpfile for your Code on basis of the comments.

Next step: automate the process so that you can have a daily helpfile for your actual code. Fast to browse with keywords for new developers.

A good thing is, that if you name your classes and methods correctly you can see in the comment quite good results.

Two examples of auto generated comment
E1
/// summary
/// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
/// /summary
/// param name=xThe first object to compare./param
/// param name=yThe second object to compare./param
/// returns
/// Value Condition Less than zerox is less than y.Zerox equals y.Greater than zerox is greater than y.
/// /returns

    public int Compare(Object x, Object y)
    {
        if (x.Weight == y.Weight)
        {
            return 0;
        }
        else if (x.Weight  y.Weight)
        {
            return -1;
        }
        else if (x.Weight  y.Weight)
        {
            return 1;
        }

        return 0;
    }

E2
/// summary
/// Handles the RunWorkerCompleted event of the backgroundWorkerPoll control.
/// /summary
/// param name=senderThe source of the event./param
/// param name=eThe see cref=System.ComponentModel.RunWorkerCompletedEventArgs/ instance containing the event data./param
private void backgroundWorkerPoll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

You just need to add on or two lines yourself to get a code documentation. Really needed at big projects were each code is reviewed.

(The next tool in line would be something like FXCop to see if your code follows the company rules)

I agree that comments need to add value to the code and need to be maintained; however, I disagree with over-reduction of comments.

Source code is designed to bridge the gap between machine logic and human communication/thought. While this makes it a great medium for telling the machine what to do, it’s not designed to be as fluent or natural as human language is. Reading code requires a mental translation to occur before you can make sense of it. Writing code requires that same process in reverse.

I comment a lot (oftentimes, every line.) I do this because if I can’t write out the code in English, I don’t understand enough of what I’m doing to be coding it. When I later revisit the code, I can read it in my own words just by reading through the comments. I also use such comments to refactor and clean up what’s going on. It’s easier to spot logical errors when you can see them in your own words.

I’m sure there’s a benefit to developing a mental process that handles this translation for you but to me it seems unnecessary. I want to focus on the essence of the code not the semantics.

I’ve always felt that methods shouldn’t need comments inside them, only comments describing the method should be enough… if that even made sense

// comments go here
private void foo()
{
// not here
}

the comments are there to describe what the method does, not how it does it. How it does it can easily be seen if you look at the code

roflmao: Are you taking the piss mate, or were you just asleep for the last 7 years?

I tend to feel that the member name and the parameter names should usually be (made to be) sufficient. Beyond that, RTFC.

This changes for binary-only distributions for developer clients, of course, which I almost never do. Mate.

This is off topic, but I would like to suggest a blog entry subject.
I was looking what you have written about build systems and found these:

  • December 06, 2004 The Magical Build Machine
  • October 26, 2006 The Build Server: Your Project’s Heart Monitor
    After a quick read it seems you have changed your mind about the importance of build servers. It would be interesting to know how many of your old blog entries contain opinions that you have changed your mind about.

Not that there was something wrong with discarding old opinions. Just curious.

While I’d rather have too many comments than too few, I agree that a good balance and few comments is best. It is quite obnoxious to work with developers that need to tell a story and comment every single fricking line. With spaces in between. So the simplest 5 line code becomes a whole page of tripe, and takes 3x longer to comprehend. But I’m not bitter.

Powerlord – Miss the point much? I don’t see Atwood as writing a unique function here… he’s just trying to illustrate that some random function doesn’t need physical comments to be descriptive.

Anyways, I’m not sure I agree 100% with what Jeff says. In other posts he reminds us that someone else will eventually have to maintain our code. I’d like to take it one step further and say that the new set of eyes might not know what you were trying to do and that is dangerous, unless you have comments in place saying what the nondescript ‘r’, ‘n’ and ‘t’. I mean, would it kill you to use variables with descriptive names? Does it really hurt to put the single line comment saying what method you’re using to approximate providing you don’t overdo it?

Good post. I read your blog all the time.

Comments or not, all the extra whitespace around your encapsulations confuse me! :wink:

This is well covered in CodeComplete, which well I guess is where you got the name of your blog from. I think Mcconnell would still say you still haven’t taken it far enough.

private double SquareRootApproximation(n) {
r = n / 2;
while ( abs( r - (n/r) ) t ) {
r = 0.5 * ( r + (n/r) );
}
return r;
}
System.out.println( r = + SquareRootApproximation® );

what is r? what is n? what is t? Certainly isn’t obvious. Your refactored example is still a Coding Horror because you are using 1 letter variable names.

As a maintenance programmer, I’d replace this function with

private double SquareRootApproximation(double value) {
return Math.Sqrt(value);
}

since it’s never explained why the algorithm is used over the built-in square root algorithm.

Even better, I’d replace SquareRootApproximation® with Math.Sqrt® directly and dump the function entirely.

P.S. Your code examples work better when they actually compile. Also, bounds checking might be a good idea, since you can’t take a square root on a negative number without going into imaginary numbers. I believe that Math.Sqrt() returns a NaN value in this case.

Suggesting that comments should be left out for readability is like pouring out the baby with the bathwater.

I’m a senior developer (25 years) and I’ve seen code that would make your toenails curl up. The junior programmers’ most favorite comments are:

  • The code is self-explanatory.
  • I didn’t have time to write comments. The schedule was too tight.
  • Comments are detrimental to legibility.

I’m sorry, but if you’re working on a project with over 10,000 modules containing 10,000,000 lines of code, a comment here and there isn’t too much too ask.

Code routinely gets thrown away because it doesn’t contain any comments, and only the original programmers know what it does.

Especially when you look at brain-damaged stream-of-consciousness code that lacks any structure or abstraction, you get cravings for comments. Otherwise, the reader might do a mark-delete and complete rewrite operation faster than the original programmer can say Stop, I’ll explain it to you!

Spaghetti code is not just limited to C, it’s also widely spread in the C++, Java and C# worlds. Bad object hierarchies, nonsensical interdependencies and so on are all around. The solution when one team is replaced by another is most often a complete rewrite, because none of the original code was documented. On the other hand, well documented code can live for decades.

I agree. well almost. Sometimes comments are life savers.

Just wrote an entry in my blog about all this and an incident which made me write more comments than ever…

http://code.zhandwa.com/2008/07/27/code-comments-do-we-need-them/

@Rob

what is r? what is n? what is t? Certainly isn’t obvious. Your refactored example is still a Coding Horror because you are using 1 letter variable names.

r should be named root or result

t should be be eps, tolerance or precision

n is a bad variable name, because numerical coding has a Fortran tradition, in which i,j,k,l,m,n are names of integer parameters. It should be replaced by x, which is short and to the point – you want to calculate sqrt(x).

@Thomas Winsnes

the comments are there to describe what the method does, not how it does it. How it does it can easily be seen if you look at the code

This is impossible to achieve in numerical code, because

x = (a - b) * (a + b);

and

x = aa - bb;

look equivalent in the code but they are not really equivalent due to floating point rounding errors. It is expecting too much from your fellow programmers to immediately recognize all the tricks you’ve done to increase numerical stability of your computation. Hence, it needs commenting.

Never Start With Comments?

As with any edict, it has a grain of truth but I think misses the mark? Just refactor your comments like code. If you aren’t starting with solid defined documentation then one of the best things to do is to pseudo code/comment code your functions and call flow. Then, you just refactor the comments with the code, removing out what is made self evident by the code itself. A touch of extra commenting won’t hurt.

I’m so glad I comment my code extensively…it really saves me a lot of time when I have a maintenance task come up two or three years after writing a bunch of complex (for me) code. When I have some difficult code to write I begin by writing an outline, as comments, of what the code should do. It helps me write it, I leave it in, and it helps me maintain it. I can’t see any reason why this is a bad thing.

/*
 *  FUNCTION:       bitcount
 *  ARGS:			n		32 bit container	
 *  RETURNS:        count of set bits
 *  DESCRIPTION:    MIT Bitcount
 *					Consider a 3 bit number as being   = 4a+2b+c
 *					if we shift it right 1 bit, we have   = 2a+b
 *					subtracting this from the original gives   = 2a+b+c
 *					if we shift the original 2 bits right we get   = a
 *					and so with another subtraction we have  = a+b+c
 *					which is the number of bits in the original number.
 *
 *					Suitable masking  allows the sums of  the octal digits  in a 32 bit  number to
 *					appear in  each octal digit.  This  isn't much help  unless we can get  all of
 *					them summed together.   This can be done by modulo  arithmetic (sum the digits
 *					in a number by  molulo the base of the number minus  one) the old casting out
 *					nines trick  they taught  in school before  calculators were  invented.  Now,
 *					using mod 7 wont help us, because our number will very likely have more than 7
 *					bits set.   So add  the octal digits  together to  get base64 digits,  and use
 *					modulo 63.   (Those of you  with 64  bit machines need  to add 3  octal digits
 *					together to get base512 digits, and use mod 511.)
 *					This is HACKMEM 169, as used in X11 sources.
 *					Source: MIT AI Lab memo, late 1970's.
 *					
 *					Unit test validated on ******
*/
unsigned int bitcount(unsigned int n)
{
    /* works for 32-bit numbers only */
    register unsigned int tmp;

    tmp = n - ((n  1)  033333333333UL) - ((n  2)  011111111111UL);
    return ((tmp + (tmp  3))  030707070707UL) % 63;
}

Jeff, do you think all these people write that comments are good just because they enjoy writing them?

I for one write comments because I have such a crappy memory, even with self-explaining methods variables they may not be self-explaining to me in 2-3 years. I often sit and think why did I do this again? finding a comment then is like finding a pearl in the muck.

TDD is a good tool for producing self-documenting functions however is not a silver bullet that replaces comments. The tests tend to be very detail oriented however it doesn’t explain the thought process behind the function.

just my 2c
Anders.

FWIW (i know this won’t get read by now), i’d advocate splitting the function into 2:

a) a public function
public double squareRootNewtonRaphson(n) {
…implementation
}

b) a private function in the module which requires it:
private double squareRootApproximation() {
return squareRootNewtonRaphson()
}

This has several advantages:

  • anyone reading the application code just seens squareRootApproximation, which is easy to understand without having to worry about implemenation details
  • anyone wanting to dig further into the implementation immediately sees that it’s implemented using newton-raphson
  • the Newton-Raphson implementation can be added to a standard library (better still, find an existing implementation which works)
  • the squareRootApproximation implementation can be easily switched, eg if it’s found that newton-raphson is not accurate enough.

As far as comments goes, the only place i’d possibly put a comment is in the squareRootApproximation header, to explain why i’d decided to use the newton-raphson method in this particular case.

Not all code can be obvious, especially if performance enhancements have been made. Long comments are typically there because the enhancement has made the code less readable. The aim of coding isn’t to make haiku, it’s to make programs work. (See @smallstepforman comment above)

Comments are also useful because hopefully it stops some loon coming along and ‘fixing’ it because they don’t understand it’s not broken.

Not all code is easy, and contrived examples always fail to impress.

The only thing better than a comment is a test, because the test should break when the code does.