Skip to main content
GameDev.net gamedev.net
🔒 Locked

Commenting code - completely useless?

Started by jtrask Jan 31, 2007 at 12:26 PM 86 replies 26.6k views
Original Post
jtrask
jtrask
I'd like to think not... but I've been learning a lot about agile dev lately, and Refactoring mentions that comments are a good indicator that a refactoring would be useful, even if it's just to extract a single line of code into a function with a clearer name. This makes sense, and all is well and good from here. Furthermore the source code of an entire project (or subsystem or once in a while even class) might not always be self-explanatory, but for something like that I would think you'd want to collect it in some other documentation (whether external or interwoven a la Literate Programming, something a bit bigger than //). I haven't yet started applying refactoring in my own code, so I've got the theory but not the practice -- can anyone offer an example or two of when comments are warranted vs. the alternatives? Thanks
Trip99
Trip99
It is an interesting point as a perfect bit of code would be written in such a way that it reads like English and hence needs no comments e.g. instead of writing:

// Fire the bullet
DoStuff()

you write

FireTheBullet()

it now needs no comment. Of course a very obvious example but it bears up in most cases. Whenever you write a comment in a function you are explaining something or maybe reminding yourself to do something. In the first case better naming of functions and variables will often do away with the need for a comment and in the second a proper to do tracking system is preferred.

I put comments above functions (using Doxygen notation) that can then help create automatic documentation but I avoid all comfents in functions as, like you say, they tend to indicate something that could be refactored.

A lot comes down to naming things correctly. Call your functions exactly what they do and do not worry about long names - nowadays with all the intellisense features in IDEs you rarely have to type out a whole name anyway. e.g. instead of

CalcTraj()

write

CalculateTrajectory()

Proper naming also allows you to spot refactorings, e.g. if you find you are putting an 'and' in the name it usually means you need two functions eg.

FireBulletAndCheckForCollision()

Should be split into two functions (refactors) and then called like:

FireBullet();
CheckForCollision();

The same goes for variable names. Always name a variable exactly what it is! If you are unsure then you are not clear on your own design and need to sort that out first. This also prevents the horrendous activity of reusing variables e.g. temp

Another use of comments may be to say 'only ever call this function with a valid pointer'. Again rather than put the comment up enforce it. e.g. in this case I would put in an assert:

assert(pointer!=0);

You need to be clear what you want to code, clear on the restrictions of each function and the one taks the function does and then name the function correctly, enforce the restrictions via error tests and verbosely name your variables etc.

Anyway an interesting topic... :)

------------------------See my games programming site at: www.toymaker.info
SimonForsman
SimonForsman
You may want to take a look at Javadoc or Doxygen. Those tools can generate documentation based on your comments.

basically you add descriptive comments above each class and method.

looking something like this:

/** * a normal member taking two arguments and returning an integer value. * @param a an integer argument. * @param s a constant character pointer. * @see Test() * @see ~Test() * @see testMeToo() * @see publicVar() * @return The test results */int testMe(int a,const char *s);


even if the comments might seem slightly redundant it does result in pretty impressive documentation (Fully browsable html covering all classes and methods in your project).
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
tstrimp
tstrimp
Simian: Doxygen can generate most of that information without special comments. I can build references of where your function is called as well.
ToohrVyk
ToohrVyk
  • // StartPage should be called before DrawPageassert ($skeleton_status === SKELETON_ACTIVE);


    My failed assertion handler in PHP automatically displays the line of code with the error, as well as the preceding comment (and a backtrace), making error messages simpler to understand than only file-line information.
  • // TODO: replace with actual function once it's doneMockDisplay();


    During development, in-code notes from programmer to programmer (and information about how to resume work) are very useful. Arguably, quite less so during maintenance.
  • (* Little optimization trick: keep the pair *)| (x,0) as p when x > 0 -> right(p)


    Small code-level information might not deserve moving to its own function (especially since it's usually a small modification), but it's interesting to leave behind for the less clever programmers.
  • // Foo's algorithm: after the loop, store is never nullassert (store);return *store;


    Although the overall algorithm may be described in detail in paper X, properties such as the above are best repeated in a comment, so that someone who does not wish to wade through an entire page of properties still understands why the function "magically" expects the store to be non-null.
gunning
gunning
Yeah sure ideally we'd never need comments, but ideally we'd only to write simple code like FireZeMeeesiles(). You're going to have to use comments a lot of times when there's no easier way to quickly tell what an algorithm does, or when it's not efficient to wrap a piece of code into a easy-to-read-function.

I only use comments though because it makes my code more colorful, green and friendly. Makes it feel alive.
....[size="1"]Brent Gunning
knowyourrole
knowyourrole
I like to think that the majority of my code is easily understandable, so I use comments quite sparingly. I do however think they are extremely useful for separating out blocks of code, just so at a glance I can tell which block does what if I'm scrolling through a page. I prefer that to having a large chunk of code in a single code block, or just separating with whitespace.
Penance
Penance
Ideals and reality rarely see eye-to-eye.

Architectures with complex template schemes, hierarchies, and special cases usually benenfit from a little comment blurb explaining how and why they work the way they do.

Even for a well-named and coded function, comments can help to clarify what is going on, especially for mathmatical or physics algorithms that other coders may not be familiar with.

Comments are usually a good idea when answers to the questions "why" or "how" about a particular piece of code are not immediately obvious.

Think about something like bump mapping and all the steps involved with it. It might make perfect sense to you, and the technique might even be well known to someone else, but how you implement it in actual code might be confusing to someone that didn't write it. It might even be confusing to you if you come back to it 4 or 5 months later.
TheTroll
TheTroll
The one thing that I think that should be commented but almost never is; the legal values for all paramters. Can you have a null for that? are negative numbers ok? Will an empty string break things.

Doing this helps the testers and also helps people that use your functions.

theTroll
LessBread
LessBread
Go back and look at some code you wrote two years ago but didn't bother to comment on and get back to me... [smile]

Why did you write it that way and not some other way? Why did you call that API and not some other one? What were you thinking at the time? What tidbit of information did you find that led you to use the approach you used?

God help the poor sucker that ends up having to maintain uncommented code. Pray that it's never you.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Nytegard
Nytegard
As was previously stated, there are certain things that just do not make sense to be refactored. Either simple lines of code, or maybe more complex lines of code that really shouldn't go into other functions.

One of the projects I use to work on involved dealing with acquiring distances between two spots on earth.

The function was incredibly long, roughly 2000 lines. OK, so it should be refactored? Well, each line of code was part of a single mathematical formula (Just 2000 lines of tans, arctans, sins, arcsins, etc). It really didn't make sense to have functions for every part of the formula. And what exactly would you put above the function? Describing the formula in the function header would even be worse to try to look at than throughout the code. At least with comments throughout the code, you have a slight idea of where exactly in the formula you are.

I would agree that maybe sometimes people overuse comments, but they help the developer tremendously to give a spot check of where you're in a function, why you're doing something in a function, etc.

*Edit*
For something like the quadriatic formula, I'd rather see

// Calculate the value(s) via the Quadriatic Formula
// x = (-b +- sqrt(b^2 - 4ac))/(2a)
bool QuadriaticFormula(double a, double b, double c, double results[2])
{
// We're not going to handle complex numbers, so check for those situations
double squarerootvalue = ...
// Remember to add AND subtract.
double numerator = ...
double denominator = ...
double x = ...
}

Than just comments in the header, or calling multiple functions within.

*Another Edit*

Also, remember, just because something is perfectly readable by you doesn't mean the person who takes it over will find it readable.

[Edited by - Nytegard on January 31, 2007 3:46:04 PM]
Ravyne
Ravyne
Comments are always a balance and it depends on the situation. While higher-level functionality is more often than not of the Literate Programming style (or should be,) lower-level functionality often can not or should not be broken up into smaller pieces for performance or practical reasons (below some granularity it no longer becomes usefull to seperate out functionality.)

For instance, I have a software rasterization library, and while I do refactor what I can (clipping for instance) many pieces just cannot be refactored without considerable performance penalty or is not appropriate to refactor because the task is already at the atomic level (A typical Bresenham's algorithm, for instance, while complex, is a single task.)

These kind of functions are the one's which *need* the classic commenting style. Personally I usually only comment small blocks of functionality (ignoring doxygen comments, which I also use) and have a code/comment line ratio of ~5:1 with generous use of line breaks and whitespace.
throw table_exception("(? ???)? ? ???");
Joakim_ar
Joakim_ar
I usually document two things:
My class interfaces, because I don't want to look in the implementation for gotchas, and
places where I call a lot of third party code, like OpenGL calls.

The latter is because I (or any maintainers) might not be into that third party API, and really shouldn't have to in order to use my API.

From time to time I also put a short comment before 10-20 lines of code to descripe what it does, since it's quicker when you want to find a specific piece of code to read a single comment than 10-20 lines, even if the code is quite clear.
IADaveMark
IADaveMark
Quote:
Original post by LessBread
Go back and look at some code you wrote two years ago but didn't bother to comment on and get back to me... [smile]
Amen, brother.

Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
Kylotan
Kylotan
As long as there is any sort of mismatch between a natural language representation of an algorithm, and a computer language representation, comments will be useful. Even the best-written source code in the most readable language will occasionally use some idiom or optimisation that is worth noting.
MaulingMonkey
MaulingMonkey
Here's a few places I use comments:

1) File copyright notices
2) FIXME:s, TODO:s, WTF:s, "Outstanding Issue" lists.
3) Explaining workarounds, or otherwise odd-looking code that cannot be refactored (e.g. external "unowned" APIs or similar)
4) "Why you got an error here and what to do about it" in C++ template code.
5) Explaining the "high level" operation of obtuse algorithms that cannot be factored out into seperate function(s) without fundamental performance/operation change issues (with the function name describing "what", the code describing "how", and the comments describing "why" we do "what" we do "how" we do it.
6) Postconditions (preconditions usually are assert()able, post conditions tend to involve dedicated, nontrivial, and seperate unit tests -- comments are for localized notes which are then to be tested by said unit tests)
CTar
CTar
Quote:
Original post by Kylotan
As long as there is any sort of mismatch between a natural language representation of an algorithm, and a computer language representation, comments will be useful.


In some cases I find the computer language representations more intuitive. So I'd instead say that it's at least needed when the code could be expressed much more naturally in a natural language, this is of course assuming refactoring have already been ruled out. Metaprogramming in languages not made for it, especially preprocessor metaprogramming in C++, often needs lots of comments.

Notes to other programmers are also a good use of comments. This could be documenting optimizations, todos, fixme, etc.
Zahlman
Zahlman
Quote:
Original post by Nytegard
For something like the quadriatic formula


Given good names for the intermediates, I really don't think that needs comments (except for the header, which documents the formula and thereby indicates the purposes of the parameters). In fact, we don't really need that many intermediates.

I'd probably write something like:

// Use the quadratic formula to solve ax^2 + bx + c = 0.// Solutions, of form (-b +- sqrt(b^2 - 4ac))/(2a), are stored in results,// assuming they are not complex. Returns whether successful.bool solve_quadratic(double a, double b, double c, double results[2]) {  double determinant = b * b - 4 * a * c;  if (determinant < 0) { return false; }  double midpoint = -b / (2 * a);  double separation = sqrt(determinant) / (2 * a);  results[0] = midpoint - separation;  results[1] = midpoint + separation;  return true;}


Way Walker
Way Walker
Quote:
Original post by Zahlman
I'd probably write something like:

// Use the quadratic formula to solve ax^2 + bx + c = 0.// Solutions, of form (-b +- sqrt(b^2 - 4ac))/(2a), are stored in results,// assuming they are not complex. Returns whether successful.bool solve_quadratic(double a, double b, double c, double results[2]) {  double determinant = b * b - 4 * a * c;  if (determinant < 0) { return false; }  double midpoint = -b / (2 * a);  double separation = sqrt(determinant) / (2 * a);  results[0] = midpoint - separation;  results[1] = midpoint + separation;  return true;}


That is art.
iMalc
iMalc
An important use of comments in the code is to warn other programmers about things that they might otherwise change which would break something.

For example, warning about an intentional missing break in a case statement migth be commented with
// Intentional fallthrough

Or other important notes to the programmer:
// This has to be called twice due to a bug that ... in version ...
// This string has to be at least 13 characters long
// Dont delete the event here as blah has already consumed it
// Warning, if you change this you might also want to change ...
// In this case don't set blah here as it will get set later if it is not set.

warnings like this in the code are invaluable.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.