Rob Pike, in his essay "Notes on Programming in C", says that he tends to err on the side of commenting less, rather than more. There appears to be a school of thought that has taken this one step further, and believes that comments are at best a necessary evil, and that good code should be self-evident enough to obviate the need for comments.
Bull.
Yes, you should be writing code that's clean enough that you don't need to explain what it does. But the code only tells you what the code does; it doesn't tell you what the code was intended to do, what it ought to do, what it doesn't do, or why it looks the way it does.
The canonical example of a useless comment is:
i++; /* Increment i */
What makes this a bad comment? Quite simply the fact that it doesn't add to the reader's understanding of what's going on. Compare this with:
for (i = 0; i < num_elements; i++)
{
frob(elements[i]);
if (elements[i] == 0)
i++; /* Ignore the next element */
}
In the first case, the comment tells you exactly what the code does, but you knew that already from reading the code. In the second case, however, the comment tells you, in human terms, what the statement is intended to accomplish. This is a minor, but crucial difference: the code tells you what the code does; the comment tells you what the code is supposed to do. If you wanted to change the code so that it used a linked list rather than an array, you would know how to translate that statement:
for (elem = elements; elem != NULL; elem = elem->next)
{
frob(elem->data);
if (elem->data == 0)
elem = elem->next; /* Ignore the next element */
}
Take a look at a good reference book. If you wanted to use this book to answer a question, you might start by looking up a key word or two in the index, or by finding a promising chapter in the table of contents. Then you would leaf through the chapter, reading section titles and table captions, until you found a page that was likely to hold the answer to your question; then you would start reading the actual text. Without the section headers, it would take much longer to find the part that you are interested in.
In order for a program to serve as its own reference manual, it should contain chapter and section headings, comments that briefly say what the code that follows does. This allows the reader to skim the comments and skip to the part that he's interested in.
In situations like these, it is especially important to leave section-header comments, lest the reader lose sight of the forest for the trees. Clearly mark what is important and what is incidental.
int
authenticate()
{
/* Find out which authentication method to use */
/* If it's a network connection, authenticate host */
/* Prompt user for password */
/* Verify supplied password */
/* If it doesn't match, raise the alarm */
}
Then, when you actually flesh this function out with code, your outline comments automatically become section header comments.
Writing such an outline carries an additional benefit; it allows you to catch, at an early stage, problems in the design itself. The human brain is a wonderful thing, but it is also a result of three billion years' worth of "good enough" implementation, and backwards-compatibility back to the earliest chordates. As a result, it is a giant hack with more than a few quirks.
One of these quirks is that the different parts of the brain don't always work together. You may have experienced "confessional debugging", in which you ask a coworker for help with a problem, but the act of articulating the problem into words or drawing a graph on a whiteboard suggests a solution. The part of your brain that sees the code is only a few neurons away from the part that can fix the problem, but the shortest path between them often leads through the speech centers, out of your mouth and back in through your ears.
Writing an outline is a variant on confessional debugging; by writing a compact, high-level summary of a piece of code, you help ensure that the design is good, and that you haven't left anything out.
In these cases, stop and add an XXX (or FIXME) comment:
fd = open("myfile", O_RDONLY);
/* XXX - Error-checking */
For one thing, this tells anyone reading your code that it's still unstable, and also points out where the known problems are. For another, if you don't mark the problems now, they'll be a lot harder to find a week or a year from now, when you're ready to revisit your old code.
Why would anyone even consider contributing to your project? In most cases, people just want to make one or two small, specific changes; perhaps they want to fix an annoying core dump or add a useful command line option. They want to find the relevant section, fix the problem, and submit a patch. Get in quickly, get out in less than an hour.
You should encourage these people. How? By making it easy to find the problem spot quickly. How? Clean code is a must, of course, but good commenting practices can also make the task much easier.
Section-header comments (see above) tell the reader what a given passage does, and allow him to get a feel for the layout of the project before diving into the code itself. Cross-references, e.g.
int
parse_line(FILE *infile)
/* This is used by (*parser->lang)() */
help to show how things are connected.
The bottom line is that if your code is too hard to read, people will find it easier to a) do nothing, b) submit a bug report and expect you to fix it, or c) switch to some other program that does the same thing as yours but is easier to hack.
To me, this sounds like saying that a highway construction crew might forget to update the road signs when necessary, so therefore there shouldn't be any highway signs. Of course this is a risk, but in the vast majority of cases, it is nice to have signs that say where the road goes, and roads that go where the signs say.
If you use tables of data in your program, you still have to maintain them, even though the compiler can't tell you whether they're wrong. They're just as much a part of your program as the actual code. So it is with comments. Don't just maintain code. Maintain code and comments.
whereas C-style comments do not;# This is a comment # <old code> # old comment
/* This is a comment <old code> /* Old comment */ this is not commented */
Consider this the next time you're designing a language.
Baby steps toward a Good Thing(tm)?
Great (succinct) article.
I agree with the idea that comments are useful, and can indeed live on a higher plane than 'a necessary evil'. I subscribe to the rule of thumb that support is ~80% of the cost of a project. Therefor, I see comments, and anything else which can help support as a top priority. I should also mention that my short term memory is not astonding :-).
I like the suggestion of adding the comments first. I had always bucked against doing a flow-diagram, or even a proper outline in my school days. Now that I have been bitten by enough of my own 'user errors', I know that the time and energy spent on a good and proper plan of action is a Good Thing. Not saying I do it 100%, but more than I did. Adding comments before code would probably move me toward the outline/flow diagrams thinking.
I wonder if this also lends itself to a bias/acceptance of what understand as Extreme Programming. Basically a more regimented version of the Open Source mantra "release early, release often".
Nice Java/C++ Style commenting
When i comment out blocks of code in order to test
a new algorythm i usually do it like this:
/* //
... code ...
// */
this allows me to add one single character to
switch that code back on:
//* //
...
// */
Don't tell me what the statement does.
Code like:
i++; /* increment i */
is encouraged by CS professors that require a certain comments to code ratio--I know, I had some.
It's useless. Try commenting "Hello World".
I write comments for several reasons: As an outline (as mentioned in the article), to explain something that is 'tricky', not obvious, or ambiguous--i.e. something that took several tries to get right or that needs multiple outcomes (a loop with several exit conditions/breaks for example), or to include a humorous comment in the code--I've always got to be the smart ass.
Re: Don't tell me what the statement does.
You don't quite pass. Yes, adding "/* increment i */" is surprising, but it is a requirement. If you were not to add that comment, your code wouldn't work in the way you need it do (pass the course). You should therefore add another comment indicating why that seemingly useless but actually very important comment is there:
i++; /* increment i */
/* The previous comment may appear
useles and redundant. However, it
is important that it be retained for
this program to meet its design criteria:
a certain comment-to-code ratio required
by Prof. Clueless. */
Can do better...
This is still an uninformative comment:
for (i = 0; i < num_elements; i++)
{
frob(elements[i]);
if (elements[i] == 0)
i++; /* Ignore the next element */
}
- since it gives no reason why we ignore the next element.
The syntax tells you its ignoring the next element, thats easy
to see. Comments should dig deeper into the semantics, and
say things like '/* ignore zero-length data packets */'
And it might also be worth commenting why the code always
calls 'frob' on the first element!
Baz
Separate code explanation
For the GNU TeXmacs program I adopted yet another strategy as commenting each function in the source code in a detailed way. Indeed, a special part of the documentation of TeXmacs is dedicated to the source code. This strategy allows you to separate writing good explanation for the code from the physical structure of this code. I only use comments in the source code in order to outcomment temporarily obsolete code (as you suggested) or in order to comment some really tricky things (this is rare).
My design choice has a perverse consequence though: hackers are not always aware of the fact that the documentation contains detailed explanations of the source code. Another strategy used by some programmers is to automatically generate documentation for the source code from "enriched source code" (i.e. Knuth's web language). However, this may again lead to overdocumented code and to explanations, which are to closely related to the source code, and which do not address the main underlying ideas behind the program.
Re: Don't tell me what the statement does.
Yup, here at univ they expect us to write code
like this (snippet from some Route66-wannabee we
had to write for our exam):
/**
* Create a new city.
*
* arguments:
* name: the name of the newly
created city.
*
* require:
* The name may not be null, nor an
empty string:
* (name null) && (name "")
*
* effects:
* A new city is created, and its
name set to name.
* getName() = name
* The list of roads is initialized
as an empty array
* of length MAX_ROADS.
* $roadList = new
Road[MAX_ROADS]
*
* exceptions:
* IllegalArgumentException: name
is null or empty string
* (name == null) || (name == "")
*/
public City(String name) throws
IllegalArgumentException {
setName(name);
initRoadList();
}
It seems overkill: 21 lines of comment to 4 lines
of actual code (which isn't even real code; it
just calls 2 other methods and that's it!)...
However, it tells someone who looks at your code
exactly what the method is supposed to do, what
it's ins and outs are, helps you anticipate on
possible catches you're likely to encounter, and
generally helps write more correct code in less
time.
Also, the occasional hacker can get in, read some
comments, identify the code-block that needs to be
altered to suit his specific needs, and do it in
far less time than it would take him to try to
understand your program by reading the code
itself...
Yes, you'll put lots of time in commenting the
stuff, but if it's a program you intend to
maintain it certainly pays off...
Needless to say that I don't comment my own code
like this... ;-)
Comments and style
It is important to realize that not everyone has the same IDE as you, uses the same tab spaces as you or has the same page width, screen depth, whatever. Code that looks good on WackyIDE may appear as chaos in vi or emacs. So if we are going to pontificate coding styles, I'd like to add my two cents: I wish people would indent with spaces rather then tabs and use returns to keep their code under 72 chars line width. And if I really get my way, the indentations will be two spaces:
#include <stdio.h>
int
main( int argc, char *argv[] )
{
int i; /* unnecessary variable */
while( I_am_opinionated ){
/*not from WI, just like That 70s Show */
printf( "hello, Wisconsin\n" );
}
exit( 0 ); /*should never get here. */
}
Re: Don't tell me what the statement does.
This commenting would have been good if you had
followed the javadoc standard. Then you could
generate really nice documentation in HTML
which would have the added feature of telling
implementors of your library how to use it.
This is how I think you should do it using
javadoc:
/**
* Creates a new city. A new city is
created, and
* its name set to name.
*
* @param name
* the name of the newly created city.
* @throws IllegalArgumentException
* name is null or empty string
*/
public City(String name)
throws IllegalArgumentException {
setName(name);
initRoadList();
}
Re: Comments and style
> It is important to realize that not
> everyone has the same IDE as you, uses
> the same tab spaces as you or has the
> same page width, screen depth, whatever.
> Code that looks good on WackyIDE may
> appear as chaos in vi or emacs. So if
> we are going to pontificate coding
> styles, I'd like to add my two cents: I
> wish people would indent with spaces
> rather then tabs and use returns to keep
> their code under 72 chars line width.
> And if I really get my way, the
> indentations will be two spaces:
>
>
> #include <stdio.h>
>
> int
> main( int argc, char *argv[] )
> {
> int i; /* unnecessary
> variable */
>
> while( I_am_opinionated ){
>
> /*not from WI,
> just like That 70s Show */
> printf(
> "hello, Wisconsin\n" );
> }
>
> exit( 0 ); /*should never
> get here. */
> }
>
The problem with your filosofy is that you are
contradicting your self, the best way to make your
code look good for any person is to use tab
instead of spaces. I personaly hate code idented
with 2 spaces (the diference between idents is
much to small), when you ident with spaces I am
lost forever or I do :%s/ /\t/g witch not always
work as desired.
Now if you had seted up you ide (and yes most of
them have this option) to use a 2 spaces tab my vi
would ajust it automagicaly to my preference of 8
spaces instead of 2. And when my code goes to your
machine it would appear correctly with the 2 space
that you prefer.
my style of commenting
I think everybody has a different style of commenting. Mine is as follows:
/* function-name: (arguments [a brief label for what they're supposed to be])- (result)
computes [tell what it does, not how it does it]
SIDE-EFFECTS: blah [of course, only if the function has a side-effect] */
blah my_function(blah)
{
... // usually I don't put any comments here at all! OTOH, my functions are rarely 10 lines
}
In addition, I always have a document somewhere that has a roadmap for how the program works. High-level, it says something like: "there are 3 major components: the parser, the type-checker, and the interpreter. Processing starts at the main function which invokes the parser with a file handle. The parser generates a parse-tree, possibly with errors. If there are errors, it additionally sets the global variable errs to the number of errors encountered ... blah blah blah ...
"The parser has an interface defined in parser.h. The type-checker has an interface defined in type-checker.h. The interpreter's interface is in interpreter.h. See those files for descriptions of how those modules work."
I find that style of commenting allows for comments that are very helpful but that don't simply copy the code: high level descriptions are very valuable because they let you quickly get a good understanding of how even a very large software package works, and function-level documentation is very good for letting future coders quickly read sections of code and understand what's happening. If you do those things and you keep your functions small, then inline comments are usually redundant -- your code ought to document itself through your choosing clear algorithms and good function and variable names. On occasion, you might need to explain why your algorithm works, but that's about it.
Re: Nice Java/C++ Style commenting
You have no choice but to use this kind of kludge in Java, but you would get nailed in my shop in in a code review in C++. ( Actually if you have code like this you should create a method for it and just comment out the invocation. This is almost always the 'right' thing to do if you are adding that much functionality. ).
#if 0 // code disabled
...
#endif
#if 1 // code enabled
...
#endif
is a better method in C++. one character is all you have to change. Your method is too 'tricky' and error prone. What if you have embedded C-style comments in your code block?
What if you forget the closing comment?
Personally I think this is one of the suckier 'features' of Java.
> When i comment out blocks of code in
> order to test
> a new algorythm i usually do it like
> this:
>
> /* //
>
> ... code ...
>
> // */
>
> this allows me to add one single
> character to
> switch that code back on:
>
> //* //
>
> ...
>
> // */
No substitute for good judgment
Hi, Andrew. Long time, no see. :)
Generally, I think your sentiments are well-reasoned. I tend to favor a standard that relies on good judgment--before adding a comment, ask yourself, "does this make my code easier to understand?" If not, the comment is probably unnecessary and likely harmful.
If the answer is "no," then ask yourself, "what is necessary to make my code easier to understand?" If the answer is "I should probably rewrite this," then rewrite it! If you don't have time to rewrite, at least add a to-do comment saying "this code sucks, rewrite it."
This answers the question of whether to comment. On how to comment -- a project's lead developer should establish an explicit, but reasonable, standard. The team should then stick to that standard.
A Java idea--the javadoc API supports extensions, so you can define project-specific tags if you feel that's worth the effort. In addition, some IDEs (eg JBuilder) recognize the @todo tag and automatically construct task lists for you. This is a huge time-saver for those who have the IDE, and it still helps out those who don't (eg, "grep @todo Blah.java"). Otherwise, "XXX" or some other reasonable header is a great idea, and I've used that extensively in the past.
Re: Don't tell me what the statement does.
If every function you code has that much documentation you could read forever before you find the information you are actually looking for. Stuff like that really should go somewhere else. (In a tech. reference for your program or something)
Comments should provide the information you need to understand it. NOTmore....
Re: Don't tell me what the statement does.
And in case anyone was wondering my post was a reply to Lord Nightwalkers post. (sorry for the double posting)
Re: Comments and style
I agree. Tabs are easiest to deal with because you can specify how large the tab is supposed to be. In VI it is as simple as :set ts=2 now I can read your code the way I want to see it.
>
> % It is important to realize that
> not
> % everyone has the same IDE as you,
> uses
> % the same tab spaces as you or has
> the
> % same page width, screen depth,
> whatever.
> % Code that looks good on WackyIDE
> may
> % appear as chaos in vi or emacs. So
> if
> % we are going to pontificate coding
> % styles, I'd like to add my two
> cents: I
> % wish people would indent with
> spaces
> % rather then tabs and use returns to
> keep
> % their code under 72 chars line
> width.
> % And if I really get my way, the
> % indentations will be two spaces:
> %
> %
> % #include <stdio.h>
> %
> % int
> % main( int argc, char *argv[] )
> % {
> % int i; /* unnecessary
> % variable */
> %
> % while( I_am_opinionated
> ){
> %
> % /*not from
> WI,
> % just like That 70s Show */
> % printf(
> % "hello, Wisconsin\n" );
> % }
> %
> % exit( 0 ); /*should
> never
> % get here. */
> % }
> %
>
>
> The problem with your filosofy is that
> you are
> contradicting your self, the best way
> to make your
> code look good for any person is to
> use tab
> instead of spaces. I personaly hate
> code idented
> with 2 spaces (the diference between
> idents is
> much to small), when you ident with
> spaces I am
> lost forever or I do :%s/ /\t/g witch
> not always
> work as desired.
>
> Now if you had seted up you ide (and
> yes most of
> them have this option) to use a 2
> spaces tab my vi
> would ajust it automagicaly to my
> preference of 8
> spaces instead of 2. And when my code
> goes to your
> machine it would appear correctly with
> the 2 space
> that you prefer.
>
I used to not comment....
But now I love to. I tried it one day and I'll never write uncommented code again. I comment so much its crazy, and thats a good thing I think.
Yeah I used to write awful spaghettie code with no indenting, no comments, nothing.
But now I don't understand why anyone wouldn't comment. Unless you type 20WPM it won't take more than a few seconds to add a good comment to eaach line, and it'll save you at least 10 times that amount of time, not to mention the money you will essentially save.
I started working on someone else's open source project, and he just doesn't comment. You get about 5 words at the top of some of the biggest functions. 500 lines of code with nothing but "Parse the file" as a comment.
I comment nearly every significant line with a useful comment, not something that explains the command. I always explain the logic behind the code. Weird things that people need to know - I explain. This often means things like 4 lines of comments for something as simple as "exit;".
Each program also has a nice explanation at the top and I use lots of headers and comments as dividers between big functions.
My goal is for any programmer (including myself) to be able to understand the logic of my code the first time through. Having to read through someone's code 15 times to get an idea of what's going on is NOT good. With little shell and perl scripts that are 30 lines that's not a huge problem, but when you're writing huge applications, good luck even keeping up with it once its 10s of thousands of lines long if you didn't comment.
Comments versus tests?
When I read this article, I was struck by the
strong parallel between comments and unit tests.
Both are meant to capture and explain the code's
functionality. Granted, comments are usually
easier to read than tests are. On the other hand,
when you run tests, you get an immediate
indication of whether the tests and the code still
agree, which is not that easy to do with comments.
There's a "comment first" coding methodology,
which the author talked about, and there is also a
"testing first" methodology, which a lot of people
follow (and I find to be very useful). Plus, with
open source unit testing frameworks (like cUnit),
it's getting easier to use unit testing for
open source projects.
Has anyone else seen the uses of comments and
tests overlap in their coding?
Harmful comments?
Well, I don't think there's any possible way that a comment could be "harmful"
By the time you stop and think "does this comment help my code more understandable?", you could have written it 3 times over, and it can't hurt your program. I sure hope no one stops to think about every comment, that could really slow down development. I say - comment away, type whatever you're thinking, it can only help your program.
Re: Comments versus tests?
I usually have tests as a lot of my "comments". I use assert() quite a lot, and have macros (that call assert) for pre() and post() which test pre and post-conditions for the function. They're basically comments but the program stops when the comment is wrong ;)
Re: Comments and style
Fact: not everyone likes the way you format code. No offence. Not everyone likes the way I format code either. We are big people. We can deal with this.
The solution is to use 'indent' (or one of the other freely available source code formatting tools). It formats code (anyone's code) the way you want. Tabs/spaces, line lengths, brace positions, everything (I think it even formats declarations... it's been a long time since I read the man page). I even use it on my own code because (surprise, surprise!) it's more consistent than I am.
I suggest writing a really simple script that invokes indent with the command line arguments of your choice so you can format anyone's code to look the way you like it.
For multi-person projects, stick it in CVS (or wherever...) so everyone can format their code with it before checking it in. Tell everyone who doesn't like their code that way to write their own script to use on code they are editing. As long as they re-indent it before they check it back in, your entire source base will remain consistently formatted, and all your developers can happily hack away in their own style.
So... stop complaining, or something.
(Aside, I'd love to be a fly on the wall when you try and tell a Java programmer to format their code to 72 character lines...
variable.variable.variable.MethodWithAReallyLongName().AnotherMethod(parameter.method(),parameter);
)
Re: Don't tell me what the statement does.
Bravo Sierra
I'm working on a DoD avionics system project right now. It's large. VERY large. VERY VERY VERY large. (get the point? :-)
Part of our SDP coding standards includes a requirement to put banners like that on all subprograms and packages (C++ coders think package==class. sort of.)
When done properly (which is about 50% of the time IMO), this is the most a TREMENDOUS help when you are told ... "HEY! Flight test just hit a problem with this code that was written 3 years ago GO FIX IT YESTERDAY!"
We also have SDP level requirements that people above were flaming to comment basically once per SLOC. I personsally stretch this a little bit and comment once per block of statements when it makes sense to me to do so.
One thing we do with comments happens during our detailed design phase. This is called PDL, or Pseudo Design Language. We basically put together the outlines of our code packages, but with comments describing what we are going to do in place of the code. This makes it easy to review work and do a massive redesign quickly. After design is over, you fill in code, and leave the descriptions. As long as you wriet go mid-level descriptive PDL, this works really well. If you get people who write PDL that would be valid Ada after you pull the comments, it doesn't work.
Since our code tends to live a very very long time and get handed fro mperson to person to person for maintenance, this level of comments is a great help.
Re: Harmful comments?
> Well, I don't think there's any
> possible way that a comment could be
> "harmful"
There is. Extraneous comments make it much harder to find the useful ones. Heck, they make it harder to find the bloody code! Believe me, if you've ever seen overcommented code, you *know* comments can be harmful.
Also, there's always the case of the misleading comment, when the comment says something *other* than what a segment of code is supposed to do or does.
Re: Comments and style
> The solution is to use 'indent' (or
> one of the other freely available source
> code formatting tools).
And, that doesnt work when the language uses identation for blocking. Ie, Python. (Please, no language wars here :)
Better to use tabs. Period.
Re: Nice Java/C++ Style commenting
> When i comment out blocks of code in
> order to test
> a new algorythm i usually do it like
> this:
>
> /* //
>
> ... code ...
>
> // */
>
> this allows me to add one single
> character to
> switch that code back on:
>
> //* //
>
> ...
>
> // */
An approach I tend to use (although people who read the code are oftentimes confused by it, even after I explain it to them) is the following:
someFunction() {
...
/* STEP 1: initialize the lot */ {
...
}
/* STEP 2: do stuff */ {
...
}
/* STEP 3: print out the results */ {
...
}
...
}
By breaking up the code in sections, and documenting it accordingly, commenting out a piece of code can be achieved as follows:
someFunction() {
...
/* STEP 1: initialize the lot */ {
...
}
/* STEP 2: do stuff */ {
...
}
if (false) /* STEP 3: print out the results */ {
...
}
...
}
This technique can also be used to keep old source code around, without impacting the object code.
Re: Comments and style
Um... no.
The whole point of my comment was that tools exist that allow everyone to use their own style. I'm know very little about Python. But the fact that it uses indentation for blocking is irrelevant to my point. I'm sure Python programmers still have their own style. Maybe there are no formatting tools for that language. Maybe there should be. Whatever.
I appologize for being so specific.
Re: I used to not comment....
> 4 lines of comments for
> something as simple as
> "exit;".
I once had a 10-line comment explaining why a certain if statement didn't have an else clause.
Section Header Comments become Function Names
I'd like to go a little further and suggest that these section headers should probably be viewed as placeholders for calls to functions that have not yet been written.
The term "section headers" implies that there is a nontrivial amount of code associated with these sections. If this is the case, then they may be better off in separate functions.
The functions, IMO, should be named descriptively, even if the name winds up a little long. (An exception would be names of functions that are called in many places, especially public functions that will be called by programmers external to the package in question.)
For example, the section headers in the example:
/* Find out which authentication method to use */
/* If it's a network connection, authenticate host */
/* Prompt user for password */
/* Verify supplied password */
/* If it doesn't match, raise the alarm */
... might transform into the following (using Java syntax):
if (getAuthenticationMethod() == NETWORK_CONNECTION) {
........if (! authenticateHost()) {
................raiseAlarm();
........}
}
boolean authenticateHost()
{
........String password = getPasswordFromUser();
........return passwordVerifiedOk( password);
}
I'm not suggesting that every section necessarily be isolated into a function. Some of these sections will be small enough so that a separate method might result in method clutter. However, I believe that most code I've seen would benefit from efforts in this direction.
Re: I used to not comment....
%
> I once had a 10-line comment
> explaining why a certain if statement
> didn't have an else clause.
This is an actual comment from one of my daemon sources:
// ===========================================================================
// This function does nothing. It is very important that this function exists.
//
// The function is called as a callback via a raised signal (SIGPIPE) when
// there is an error on the socket between the directory and monitor daemons.
// If this function does not exist, the daemon will crash. Please don't
// remove it!
// ===========================================================================
static void handleDisconnect(int signal)
{
}
I have to say that I actually enjoyed writing that comment :-)
Re: I used to not comment....
> %
> % I once had a 10-line comment
> % explaining why a certain if
> statement
> % didn't have an else clause.
>
> This is an actual comment from one of
> my daemon sources:
> //
%
===========================================================================
> // This function does nothing. It is
> very important that this function
> exists.
> //
> // The function is called as a
> callback via a raised signal (SIGPIPE)
> when
> // there is an error on the socket
> between the directory and monitor
> daemons.
> // If this function does not exist,
> the daemon will crash. Please don't
> // remove it!
> //
%
===========================================================================
> static void handleDisconnect(int
> signal)
> {
> }
>
> I have to say that I actually enjoyed
> writing that comment :-)
>
#include <signal.h>
int main(int ac, char *av[]) {
...
signal(SIGPIPE, SIG_IGN);
...
}
Re: Nice Java/C++ Style commenting
The fact that 'people who read the code are oftentimes confused by it, even after I explain it to them' means that it is poor style. The whole point is to make it so that someone will understand it without your explanation. You are off doing something more interesting somewhere else, and the poor maintainer doesn't have the benefit of your brilliant insight.
BTW the way your method does add runtime overhead, because you have to evaluate all the if(false)'s. They add up over time. They also add potential problems when some helpful maintainer changes false to true. Besides, this is really just a workaround the Java brain dead lack of a pre-processor. Java is such a fascist language, designed to be moron-proof. Obviously that design qoal is a total failure. Or as I like to say, 'Java: designed by morons for morons'. Only (half) kidding.
OABTW I only assume you are using Java. If you are using C/C++ you need to take a remedial course in preprocessor directives. Fast.
%%
> An approach I tend to use (although
> people who read the code are oftentimes
> confused by it, even after I explain it
> to them) is the following:
>
> someFunction() {
> ...
> /* STEP 1: initialize the lot */
> {
> ...
> }
> /* STEP 2: do stuff */ {
> ...
> }
> /* STEP 3: print out the results
> */ {
> ...
> }
> ...
> }
>
> By breaking up the code in sections,
> and documenting it accordingly,
> commenting out a piece of code can be
> achieved as follows:
>
> someFunction() {
> ...
> /* STEP 1: initialize the lot */
> {
> ...
> }
> /* STEP 2: do stuff */ {
> ...
> }
> if (false) /* STEP 3: print out
> the results */ {
> ...
> }
> ...
> }
>
> This technique can also be used to
> keep old source code around, without
> impacting the object code.
>
NASA and the Space Shuttle flight programs
Apparently each line of the space shuttles flight
program has something like a full page of
documentation. (I am assuming it's not all inline).
Every bit of real code has an explanation of what
it supposed to do, and some sort of mathematically
rigorous proof of why it's correct.
If they run into a real runtime error, the group
gets together and figures out what's wrong with
their programming process, instead of pointing
fingers and getting mad.
The result: apparently they have had just 17
runtime errors of any nature at all since the
inception of the shuttle program.
How's that for a result of good documentation?
Re: Don't tell me what the statement does.
You'd actually be better off of you actually did this..
Once you start on a real project with oder coders
involved ,youll understand.
And Most java IDEs can autogenerate the skeletons
for code like this, you just fill in..
The example of good commenting.
http://java.sun.com/j2se/1.3/docs/api/index.html
are on of the best examples on how comments
are useful.. (the docs are autogenerated straight from sourcecode.)
Thanks
I read that article while mentally saying "yeah, yeah, that's right, I do that" and finished feeling a bit smug and wishing it had said something "more interesting".
But then I went and looked at the code I've been writing and, really, it could do with more comments...
So thanks :-)
Re: I used to not comment....
Mmmm. I missed out the fact that the code has to work across 4 architectures (Sun, Linux, SGI, and HPUX). After banging my head against different implementations (and it's a multithreaded daemon, with SIGPIPE being useful for some threads and not for others) I eventually decided to handle the signal in the code :-)
Simon
javadoc like commenting..
i'm surprised that nobody mentioned javadoc (http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/javadoc.html) like commenting. Javadoc makes making documentation a whole lot easier.
You just have to include
/**
* This is a doc comment.
* @see java.lang.Object
*/
all those after the @ sign are headers for the documentation for that specific functions. There are other utilities for C as well that can autogenerate documentation like this. BTW this was mentioned in an article relating to documentation, here in Freshmeat. Worth mentioning in an article on commenting.
also
#ifdef 0
/* large code piece here */
#endif
could be used for commenting out large code pieces which does have comments inside making commenting out a headache.
Meaningful Variable Names and Indentation
Comments are very useful no doubt, but what some people don't understand is that they are no excuse for not giving meaningful variable names to your variables. When I was working on my "Intro to DSP" Matlab assignments, I gave my variables long names such as "filters_in_fourier_domain" etc. and my partner and another fellow students, said I should make the names shorter and say what they
should do in a comment.
But naturally, such methods cause other people who review the code to lose track of what's going on in the code pretty quickly.
There are some common abbreviations that can be used, like "init" for initialize or "alloc" for allocate, but otherwise name should be useful.
Another important thing is to indent the code, even
inside the same statement (I'm talking about C or perl not about python), which also eases readability.
In any case, I wrote a program called "Freecell Solver" (which is here on Freshmeat) and a fellow Linuxer said she thought that it was not already clear what I wanted to accomplish in certain parts of the code. Therefore, I added a lot of comments at the current development branch (1.5.x). The ironic thing is that Freecell Solver comes with many documents that describe its usage.
Comment data structures, not code
I believe that if your code requires a significant amount of comments to understand it chances are that it is poorly written code. The underlying <B>data structures</B>, however, should have copious amounts of comments about their structure, model and most importantly any <B>assumptions</B> they make. The assumptions are the hardest part, of couse, because the problem with something you take for granted is that you are not aware that you are taking it for granted.
Re: Don't tell me what the statement does.
> Since our code tends to live a very
> very long time and get handed fro
> mperson to person to person for
> maintenance, this level of comments is a
> great help.
Can you give an example of this? I'd be particularly interested in a function that seems to appear in a lot of your systems -- onlyShootDownAllies()
;-)
Re: Harmful comments?
%Believe me, if you've ever
> seen overcommented code, you *know*
> comments can be harmful.
Never had any of the problems you described. You might say my programs have more comments than code, is that "overcommented"?
Never had a problem finding the code, its simple, look for lines that don't start with //
Never had a problem finding the useful comments, they're all useful.
Yes, I write excessively "overcommented" code. Every day I make modifications to my code that only take me a few minutes because of the neat little headers and comments I put everywhere. What else would I do? Go through each line of code 1 by 1 because they weren't clearly commented? And what if I wrote 10 scripts this week, how could I possibly remember everything about every one? With "overcommenting", I don't have to.
Re: Nice Java/C++ Style commenting
> /* //
> ... code ...
> // */
Even nicer than this, is when you want to toggle
between two sections of code thus:
//*
code 1
/*/
code 2
// */
You can choose between code 1 and 2 by
removing the very first /
Most colorizing editors get this right, whereas
they wouldn't get #if 0/#if 1
Stephen.
Heh... 'block'-heads style of commenting...
I think I see another problem with this idea (at least if you were working in C++); variables are local to each individual block (that is, the curly braces acting as a block). Ergo, each block would find itself acting as an island unto itself.
If you're going to do that, you may as well split them up into separate functions and call each function in the correct order from within another function.
Otherwise, someone who attempts to quickly resolve some problem in your code (not that you ever make a mistake or anything) will wonder why variable 'x' seems to be going out of scope in the second block.
And, as another person pointed out, if you're doing something that a lot of other people cannot quickly grasp, (especially after you explain it to some of them), chances are you might want to rethink what you're doing. Computer languages serve roughly two purposes: 1. to permit the computer to understand your instructions, 2. to permit a human to understand your instructions. I think a lot of folks focus on #1 so much they miss #2.
All that said, please forgive the pun I saw for the subject of my reply. I honestly couldn't resist.
Re: Comments and style
> The solution is to use 'indent' (or
> one of the other freely available source
> code formatting tools
Definately the way to go.
I tried introducing a program like indent to my office, because we have some truly horrible problems with badly indented code. Some folks use tabs, some folks use spaces (and even these of different length), and nobody would re-indent the code appropriately. It lead to some extremely unmanageable code.
I felt the introduction of an indent-like tool worked much better than another programmer's draconian idea of imposing 'always use 4 space indents' on everyone else (a personal preference of his, I might add).
When I introduced it, the programmer with the draconian idea wanted to figure out a way to stream all code through it before it went into the source versioning system. Frankly, such an idea wouldn't be too bad, if it also did the same thing streaming out of the system.
Re: Comment data structures, not code
%
> % I believe that if your code requires
> a
> % significant amount of comments to
> % understand it chances are that it
> is
> % poorly written code.
%
%
> You'll never be able to write code
> that is as readable as English
> (comments). Good luck trying.
%
> There is such a thing as poorly
> written code, but that has nothing to do
> with comments.
%
> Here's a php function I use, should I
> do this instead of comments?
%
> function
%
this_function_queries_the_mysql_database_for_all_recent_articles()
> {
%
%
> $this_variable_stores_the_output_from_the_query
> = @mysql_query(blah blah);
> ...
> ...
> }
%
%
%
> no comments needed there - is it well
> written code?
%
Note: I changed the function name above from:
this_function_queries_the_mysql_database_for_all_recent_articles\
_and_their_authors_ordered_by_the_date_they_were_written\
and_displays_the_results_in_HTML_tables()
to:
this_function_queries_the_mysql_database_for_all_recent_articles()
Not to belittle the extremity that Jeff Cabaniss
was trying to put across, but it was causing the
page to stretch unnecessarily horizontally on most
web browsers.
Andypoo.
(Jeff's original message has been deleted and is
quoted above for reference, sorry Jeff)
Re: Don't tell me what the statement does.
> This commenting would have been good if
> you had
> followed the javadoc standard.
Heheh, I heard of Javadoc, but never used it. This is the commenting style the profesoor at university uses. Javadoc makes more sense though, thanks for pointing it out to me. If I ever need to write another java program again (let's hope not), I'll be sure to read up on some javadoc documentation.
Um, hello?
Pretty good article (and thanks for the Pike link, I always enjoy reading Pike), but...
for (elem = elements; elem != NULL; elem = elem->next)
{
frob(elem->data);
if (elem->data == 0)
elem = elem->next; /* Ignore the next element */
}
Um, pardon my French here, but this code sucks!
Consider the case that elem->data == 0 for the _last_ element, i.e. the one that has a next pointer that is NULL! In that case, the "skip" will set elem to NULL, and the for-loop's increment part will then happily try to compute "NULL->next", which will probably result in a segfault or some comparable evil.
Re: Um, hello?
>
> Pretty good article (and thanks for
> the Pike link, I always enjoy reading
> Pike), but...
>
> for (elem = elements; elem != NULL;
> elem = elem->next)
> {
> frob(elem->data);
> if (elem->data == 0)
> elem =
> elem->next; /* Ignore the next
> element */
> }
>
> Um, pardon my French here, but this
> code sucks!
>
> Consider the case that elem->data
> == 0 for the _last_ element, i.e. the
> one that has a next pointer that is
> NULL! In that case, the "skip" will set
> elem to NULL, and the for-loop's
> increment part will then happily try to
> compute "NULL->next", which will
> probably result in a segfault or some
> comparable evil.
I think that code was just for an example
Re: Comment data structures, not code
> Not to belittle the extremity that
> Jeff Cabaniss
> was trying to put across, but it was
> causing the
> page to stretch unnecessarily
> horizontally on most
> web browsers.
>
> Andypoo.
>
> (Jeff's original message has been
> deleted and is
> quoted above for reference, sorry
> Jeff)
>
Yes, sorry about that, I didn't notice the prblem until after I posted the message... I would've edited it if possible
Re: Comments and style
> When I introduced it, the programmer
> with the draconian idea wanted to figure
> out a way to stream all code through it
> before it went into the source
> versioning system. Frankly, such an
> idea wouldn't be too bad, if it also did
> the same thing streaming out of the
> system.
Frankly, such an idea is necessary when you're sharing a source control system. Otherwise, the diffs get cluttered with a bunch of meaningless whitespace changes. Better to run "indent" on the way in, using an agreed-upon canonical form for the repository, then run "indent" on the way out to format things to your personal taste.
Re: Nice Java/C++ Style commenting
> BTW the way your method does add
> runtime overhead, because you have to
> evaluate all the if(false)'s. They add
> up over time.
Actually, using "if false" and "if true" doesn't add any runtime overhead to Java - when the source is compiled into bytecode, the Java compiler will strip out code that will always evaluate to false, and will just yank the conditional for blocks that will always be true. Setting a DEBUG constant to true or false is a pretty effective way to turn several blocks of code on and off at the source level in Java without runtime overhead or having to worry about commenting/uncommenting all over the source code.
Re: NASA and the Space Shuttle flight programs
Wow, that is an amazing fact. Where did you get it from? That really does explain how it is so important that commenting and documentation is done. Stuff like that is needed in such high-risk things such as the space-program.
> Apparently each line of the space
> shuttles flight
> program has something like a full page
> of
> documentation. (I am assuming it's not
> all inline).
>
> Every bit of real code has an
> explanation of what
> it supposed to do, and some sort of
> mathematically
> rigorous proof of why it's correct.
>
> If they run into a real runtime error,
> the group
> gets together and figures out what's
> wrong with
> their programming process, instead of
> pointing
> fingers and getting mad.
>
> The result: apparently they have had
> just 17
> runtime errors of any nature at all
> since the
> inception of the shuttle program.
>
> How's that for a result of good
> documentation?
This #
#!/usr/bin/perl
# this is a perl script
# this is a comment
# this used to be a blank line
while # loop
(1) # forever
{ # begin block
print "Hello World\n"; # output `Hello World', and a newline character
sleep 5; # sleep five seconds
} # end block
__END__
This program forever loops a block that outputs `Hello World', with 5 seconds time between output commands.
Re: NASA and the Space Shuttle flight programs
Apparently each line of the space
shuttles flight
program has something like a full page
of documentation.
Every bit of real code has an
explanation of what
it supposed to do, and some sort of
mathematically
rigorous proof of why it's correct.
The result: apparently they have had
just 17
runtime errors of any nature at all
since the
inception of the shuttle program.
They estimate that there are about 50 bugs
remaining. Not bad for 500,000 lines of code.
But, they spent about $20,000 per line of code.
This is about as much as the hardware.
And, all process aside, an audit suggested that
the real knowledge of why the thing works
the way it does is passed by word of mouth.
If what you want is bug free code, looking at
the shuttle code processes can be of help.
Testing is also required. Judgement is also required.
If you want understandable code, you need
documentation at more than one level. The
'skip next record' example shows documentation
at a slightly higher level of abstraction than the
code. Section comments are slightly higher
still. A function header can (with proper judgment)
describe a slightly higher level. Often, comment
levels above this are entirely omitted. Thus,
there often is no 60,000 foot level overview,
outside of the user documentation (if any).
Historically, Berkeley 'tar' had something like
three comments for 720 lines of code. One said
that this was 'tar'. Another was of the 'increment x'
class. The third commented out a line of code.
Yet, the result was pretty easily followed, despite
it's unique handling of command line arguements.
The user documentation (man page) told you what
the program did (though not why you might want it).
Sparse commenting for small projects should be
examined.
My commenting style is pretty verbose. I try
to answer the obvious 'why' questions. Why
would someone want this program? Why was this
function written? Why was this unusual code
written? The code answers most other questions.
I assume that the reader knows the language,
and try not to duplicate the code in the comments.
If the comments don't match the code, then
it is likely that both are wrong.
Re: Harmful comments?
Well, I don't think there's any
possible way that a comment could be
"harmful"
Unterminated comments have, on occasion,
resulted in code that compiled, but did not run.
It can be hard to locate such defects. A comment
stripper can help. I have one (for C) that can show
just the code, or just the comments. I would not
have written it if I didn't need it.
I use #if for commenting out code, since
they can be nested, and don't interfere with
comments (which in C don't nest).
I've seen very old C code (predating the C preprocesser) that
used if (0) { ... }, which the compiler recognized,
and would omit (if there were no labels in the block).
Re: Comments and style
> Um... no.
>
> The whole point of my comment was that
> tools exist that allow everyone to use
> their own style. I'm know very little
> about Python. But the fact that it uses
> indentation for blocking is irrelevant
> to my point. I'm sure Python
> programmers still have their own style.
> Maybe there are no formatting tools for
> that language. Maybe there should be.
> Whatever.
>
> I appologize for being so specific.
Agreed... I dont know what I was smoking when I wrote that :)
Re: I used to not comment....
>
> But now I love to. I tried it one day
> and I'll never write uncommented code
> again. I comment so much its crazy, and
> thats a good thing I think.
>
> Yeah I used to write awful spaghettie
> code with no indenting, no comments,
> nothing.
>
> But now I don't understand why anyone
> wouldn't comment. Unless you type 20WPM
> it won't take more than a few seconds to
> add a good comment to eaach line, and
> it'll save you at least 10 times that
> amount of time, not to mention the money
> you will essentially save.
>
> I started working on someone else's open
> source project, and he just doesn't
> comment. You get about 5 words at the
> top of some of the biggest functions.
> 500 lines of code with nothing but
> "Parse the file" as a
> comment.
>
> I comment nearly every significant line
> with a useful comment, not something
> that explains the command. I always
> explain the logic behind the code. Weird
> things that people need to know - I
> explain. This often means things like 4
> lines of comments for something as
> simple as "exit;".
>
> Each program also has a nice explanation
> at the top and I use lots of headers and
> comments as dividers between big
> functions.
>
> My goal is for any programmer (including
> myself) to be able to understand the
> logic of my code the first time through.
> Having to read through someone's code 15
> times to get an idea of what's going on
> is NOT good. With little shell and perl
> scripts that are 30 lines that's not a
> huge problem, but when you're writing
> huge applications, good luck even
> keeping up with it once its 10s of
> thousands of lines long if you didn't
> comment.
>
>
>
Actually, then there's my ad-hoc C/C++ code.
There's just something wrong with something that looks like an entry to the Obfuscated C Contest, except it breaks the length restriction, especially if it contains /*ermm...*/ embedded in the 22nd line as the only comment visible on my 1600x1200 screen using a 12 pixel font.
Even worse (with the code in question), is that the code would just not work if the comment was chamged, added, removed, or just plain moved.
At least the code worked (I think)... but I have never done anything that bad again.