# And what father is there among you, who,
# if his son asks for a slice of bread,
# will offer him a stone?
# or if he asks for a fish,
# will instead of a fish offer him a snake?
my $fish = 'one-fish two-fish red-fish blue-fish';
my $snake = 'oooh! a snake! ooh! snake! ooooooooo!";
(Unit test proceeds to insert both $snake and $fish into a cache object, does a little bit of extra manipulation to recreate the error condition, requests 'fish' back, and -- until the code was fixed -- got the contents of $snake instead.)
That's right. A successful combination of biblical allusion with Dr. Seuss and _Badger Badger Mushroom Mushroom_.
One of those reminded me of the following legend that gets passed around here at work.
A codebase had been maintained by a single person, who then left the company. When the other engineers took over responsibility for the project, they discovered, to their dismay, that it was almost entirely bereft of comments.
Amongst the tens of thousands of lines of code, they found only one comment, preceding an unintuitive bitmask operation:
/* gok */
Nobody could work out what on earth "gok" could mean, let alone why the previous engineer had chosen to leave that comment when they found no reason to comment any other part of the project.
Years later, somebody bumped into this chap at a conference and managed to ask him about the project and the significance of "gok."
"Oh, that's easy. It stands for 'god only knows.'".
Ad company I work for buys one of our traffic partners. I'm code reviewing their system to document it and find a comment describing how they defraud us.
Netcat is full of great comments. Here's a good one:
/* I really want to strangle the twit who dreamed up all these sockaddr and
hostent abstractions, and then forced them all to be incompatible with
each other so you *HAVE* to do all this ridiculous casting back and forth.
If that wasn't bad enough, all the doc insists on referring to local ports
and addresses as "names", which makes NO sense down at the bare metal.
What an absolutely horrid paradigm, and to think of all the people who
have been wasting significant amounts of time fighting with this stupid
deliberate obfuscation over the last 10 years... then again, I like
languages wherein a pointer is a pointer, what you put there is your own
business, the compiler stays out of your face, and sheep are nervous.
Maybe that's why my C code reads like assembler half the time... */
netcat.c is by far one of the most entertaining code reads out there. Because of the unix networking / portability rants -- which are sometimes informative -- and also because the Hobbit was such a strange, scatalogical creature...
grep -in poop netcat.c
110:struct host_poop {
115:#define HINF struct host_poop
117:struct port_poop {
122:#define PINF struct port_poop
163:HINF ** gates = NULL; /* LSRR hop hostpoop */
169:PINF * portpoop = NULL; /* for getportpoop / getservby* */
336: cross-check the host_poop we have so far against new gethostby*() info,
340:int comparehosts (poop, hp)
341: HINF * poop;
349: if (strcmp (poop->name, hp->h_name) != 0) { /* case-sensitive */
351: if (strcasecmp (poop->name, hp->h_name) != 0) { /* normal */
353: holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
360:/* gethostpoop :
361: resolve a host 8 ways from sunday; return a new host_poop struct with its
365:HINF * gethostpoop (name, numeric)
371: register HINF * poop = NULL;
397: poop = (HINF *) Hmalloc (sizeof (HINF));
398: if (! poop)
399: bail ("gethostpoop fuxored");
400: strcpy (poop->name, unknown); /* preload it */
411: strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
413: memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA));
414: strncpy (poop->addrs[x], inet_ntoa (poop->iaddrs[x]),
415: sizeof (poop->addrs[0]));
418: return (poop); /* inverse stuff, we're done. */
421: for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) {
422: hostent = gethostbyaddr ((char *)&poop->iaddrs[x],
426: poop->addrs[x]);
428: (void) comparehosts (poop, hostent);
432: memcpy (poop->iaddrs, &iaddr, sizeof (IA));
433: strncpy (poop->addrs[0], inet_ntoa (iaddr), sizeof (poop->addrs));
435: return (poop);
437: return (poop); /* the full DNS hair */
443: strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
444: hostent = gethostbyname (poop->name);
447: poop->name);
449: (void) comparehosts (poop, hostent);
453:/* whatever-all went down previously, we should now have a host_poop struct
456: return (poop);
457:} /* gethostpoop */
459:/* getportpoop :
460: Same general idea as gethostpoop -- look up a port in /etc/services, fill
461: in global port_poop, but return the actual port *number*. Pass ONE of:
466:USHORT getportpoop (pstring, pnum)
476: portpoop->name[0] = '?'; /* fast preload */
477: portpoop->name[1] = '\0';
495: strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
509: return (getportpoop (NULL, x)); /* recurse for numeric-string-arg */
514: strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
536: sprintf (portpoop->anum, "%d", x); /* always load any numeric specs! */
537: portpoop->num = (x & 0xffff); /* ushort, remember... */
538: return (portpoop->num);
539:} /* getportpoop */
994: gethostpoop wants a string and there's much gnarlier code out there already,
1002: whozis = gethostpoop (bigbuf_net, o_nflag);
1451: portpoop = (PINF *) Hmalloc (sizeof (PINF));
1545: gp = gethostpoop (optarg, o_nflag);
1572: o_lport = getportpoop (optarg, 0);
1584: wherefrom = gethostpoop (optarg, o_nflag);
1654: whereto = gethostpoop (argv[optind], o_nflag);
1669: curport = getportpoop (argv[optind], 0);
1713: hiport = getportpoop (cp, 0);
1719: loport = getportpoop (argv[optind], 0);
1740: curport = getportpoop (NULL, curport);
1749: whereto->name, whereto->addrs[0], curport, portpoop->name);
1768: whereto->name, whereto->addrs[0], curport, portpoop->name);
I've commented before that I feel that the PostgreSQL project is especially wonderful about code comments. According to the cloc tool, their C code has 700k lines of code and 221k lines of comments. That by itself isn't terribly impressive if you've seen a lot of the typical boilerplate comments a lot of IDEs place in code, but have a look at a sample of the actual comments : https://github.com/postgres/postgres/blob/master/src/backend...
Thoughtful, meaningful, and high-level. I aspire to this.
This is another one from the same project that I particularly liked:
/* So you want to know the relation between the hardware and the
software control constants. Well,
/---/\/\---||---\
| R2 C |
R1 | |\ |
e--/\/\----|-\___________|____v
2.5v-------|+/
|/
Kh = Ks/(2^ix) = R2/R1
Ih = Is/(2^ix)/dt = 1/R1/C
Capstan Drum
dt 1/1800 1/100
ix Cix Vix
*/
This tangentially reminds me of the fact that every time I'm writing a comment that's longer than 4 lines and explaining in detail why the thing following works as it does, then both the comment and the thing it was explaining won't survive the next hour.
When you need more than two lines to explain something, then something is wrong and you'd better fix it.
But maybe the act of writing the comment helps to free the brain to find a better solution.
This is absolutely not true. Perhaps you are not choosing the right time to sit down and comment. I'll usually put in quick comments as a module is under construction. Once it reaches stability (meaning, I am moving on to something else) the detailed comments go in.
Also, if we are talking about embedded there are a lot of comments that are invariant because they might explain details of the hardware interface this particular chunk-o-code might be dealing with. That hardware --external to the chip you are programming-- will not change unless a hardware revision is done, which is far less frequent than code iterations.
You can't see this from just looking at the code: there are four other systems that interact with the same database. I've managed to localise the problem by the timing of faults, it seems like Cassandra is erasing entries that aren't on its local list.
They won't let us change this because they're afraid of breaking the system.
If Alec's still in charge, you're effectively out of luck. If the boss has changed, try asking about changing it again.
Letting people ask these questions freely would destroy the community. They would grab all attention, and the focus would be on creating clever questions and answers, not providing good help for developers. Kinda how the biggest sub-reddits work; content that is easy to diggest grows quickly to the top.
> question is now closed, I think 528 "answers" is probably enough, no? :) – Jeff Atwood
It is annoying, though, how so many useful SO questions get closed for various reasons when they are just the question I want answered. Perhaps the real problem is Google giving a lot of weight to SO answers, even when they are closed?
It's the kind of thread that really has no home. Proggit would shoot it down for being frivolous, HN would probably do the same if it was a self-post.
I'm glad that StackOverflow leaves closed questions visible. A lot of the value I get from SO comes from opinion-y questions getting answered by experts.
I once posted a question citing reason I thought it was not duplicate even citing each of the few similar 'duplicate' questions I could find which did not answer my specific question.
Yes, and deservedly so. It's not a question with an answer, it's not even a poll. Other communities would close it as "Chatfilter" or "GTKY". What's interesting is that it was ever allowed on SO, and that it stood as acceptable for so long. And I wonder if the fact that there was a time in SO's lifecycle where it was accepted was important to the site's success. It's the sort of question that fosters community and good will in a way that "MVC 4 Validation using Data Annotations and Jquery" does not.
This is one of the things that really bugs me about a lot of open source and Github code: almost no comments.
It almost seems that there's a generation of programmers being taught that comments are a waste of time. I really don't know where this trend comes from. Lazy? I don't want to believe that.
For my purposes it is a huge negative mark if a programmer is not religious about commenting code. I will not hire someone like that. Why? Developing code is a huge financial investment, yes, but there are other metrics that are far more important than money. If you are doing something non-trivial it often requires a lot of thought, discussion, testing, experimentation, failures, iterations and decisions. Comments within code should be used to document some of this. Document intent, thinking, problem solving approach, corner cases, decisions, where/how it could be improved, performance notes, etc.
This and the code become incredibly valuable. It means that months or years later someone can go back into the code and truly understand what it does, why it does it that way, where it came from and, perhaps, how it could be improved. You don't need to engage in a research project in order to pick-up where the last programmers left of and continue moving forward. In addition to that I firmly believe a well-commented code-base is far more valuable during an acquisition than a thousand files of code with hardly a comment.
I can think of a number of Github projects I've come across with nearly zero comments. What you are looking at is dozens or hundreds of files vomited upon your hard drive that, yes, might perform a useful function at that point in time yet would be a nightmare to dive into to maintain them in any way. Before someone jumps down my throat: Just because something is FOSS it doesn't mean we should not critique such practices. If everyone took the time to thoughtfully document their code the FOSS ecosystem would probably evolve at a faster rate. Some of these packages are so dense they are virtually impenetrable without cubic hours of work deciphering the rats nest of files.
The counterargument is that code should be self-documenting. If code is complicated enough to need comments, refactor it. Behavior should be obvious from function and variable names. If you can't say what a method does in its name, it's too big. The best code transcends the need for comments.
What you describe about the development process, to write down the thinking and edge cases and decisions and such, is important but doesn't really belong in the source code. That stuff belongs in your issue tracker system or the commit messages. What other medium tries to embed a description of the creative process in the work itself? Da Vinci didn't write on the back side of the Mona Lisa the production process for his paints. Tolkien didn't explain how he created the Elvish language in the text of the novels. There's accompanying material for that.
But realistically for software, that accompanying material is not going to get read elsewhere, or survive long-term through migrations to different tools and hosts. So it ends up in the source as the only way to keep it with the code and visible ten years later. Commenting is a least-bad solution, not a good one.
And of course, policies for code commenting never work. You just get scintillating gems like "x+=5; //add 5 to x".
> It almost seems that there's a generation of programmers being taught that comments are a waste of time.
That might be true. I had at least one professor who discouraged comments. He said, "I know how to read code." I can understand that in his particular case, he didn't need documentation for higher-level understanding. He taught us the algorithms and data structures being used and he gave us a boiler plate design that we had to conform to. All we had to do was fill in the function bodies and write a main() function.
Unfortunately, it's possible that some students might have adopted that as an overall attitude without recognizing that the context in which it was said invalidated the need for comments for any higher-level understanding. A lot of students looked up to this professor.
That's just a single example. I have no idea how common this is.
// Don't remove this comment, or the next line will break. WTF?!?
Turns out, we had mixed carriage returns and line feeds in our source. We had some UNIX coders, and some Windows coders. The Windows coders were in VS6 (ug), and the IDE showed the code perfectly. The compiler, on the other hand, was getting confused because one file had mixed CR/LF... So, essentially, it thought
// Comment
formatHardDrive = true;
It thought that pesky next line was still part of the comment. It wasn't literally formatting the hard drive... that was another bug we encountered, one time... oh, the places you'll go...
I think the best one that I didn't write was a long back-and-forth argument in a C header file where TRUE was defined as 0 and FALSE as non-zero. The original author of this product apparently had screaming fights about that being THE RIGHT WAY. Of course that surprised a lot of developers over the years and had been "fixed" several times only to be reverted back.
Pretty sad that all these examples are bad comments not good ones.
Here's a comment from some code that I posted to my blog. The idea was that this would explain in detail to someone reading the code what I was doing with the pieces of a wooden train set. This was critical to the operation of the program and I imagined that many of the readers of the code would need a careful explanation.
It turns out that I'd forgotten what this code does so the comment was helpful.
# The 15 possible pieces: a straight edge (which has $unit length) and
# is used as the measurement for everything else, a bridge (which is
# twice the length of the straight edge; it is actually supplied in
# two pieces but for the purposes of this program is considered to be
# a single piece) and a curve (using $radians_in_curve above the
# length of the straight line between the ends of the curve is
# calculated).
#
# Each entry consists of three parts:
#
# length: the length in a straight line between the ends of the piece
# at its centre.
#
# angle: the angle (in radians) between the straight line through the
# piece and a tangent to the curve at the piece's start. This only
# applies to curved pieces where the straight line is the line joining
# its two endpoints.
#
# count: how many of these pieces are supplied.
#
# Note that curves can be placed in either a clockwise or
# anticlockwise direction. The program detects this by looking at the
# angle. If it's non-zero then the piece has two orientations.
my %pieces = (
Bridge => { length => $unit * 2,
angle => 0,
count => 1 },
Straight => { length => $unit,
angle => 0,
count => 2 },
# Here's a curved piece, the angle a is $radians_in_curve, the
# length l of a side is $unit. So length is the distance between
# the points labelled s and f. Bisect the angle a you get a right
# angle triangle with hypotenuse of length $unit and angle at the
# vertex of $radians_in_curve/2. So the angle b is $PI/2 -
# $radians_in_curve/2. By simple trigonometry the length is twice
# $unit * cos($PI/2-$radians_in_curve/2).
#
# s
# C
# . . C
# . b C
# l . . C
# . C
# . . C
# . a C
# . . . . . . . C
# o f
#
# To calculate the angle to the tangent at point s (the angle c),
# note that the angle formed by os and the tangent is a right angle
# (since os comes from the centre of the circle). So b+c is $PI/2
# but b is $PI/2 - $radians_in_curve/2 and so c is
# $radians_in_curve/2
#
# s
# .
# . . .
# . b c .
# l . . .
# . .
# . . .
# . a .
# . . . . . . . . . . .
# o f
#
Curve => { length => 2 * $unit * cos($PI/2-$radians_in_curve/2),
angle => $radians_in_curve/2,
count => 16 }
);
That's beautiful! I have lately been encouraging all my team to take advantages of comments to document the high level business logic as it was at the time of development. It provides utility during code review and future dev, and it's a terrific CYA when debating with stakeholders about what they said they wanted then versus what they "remember" asking for.
/*
* If the new process paused because it was
* swapped out, set the stack level to the last call
* to savu(u_ssav). This means that the return
* which is executed immediately after the call to aretu
* actually returns from the last routine which did
* the savu.
*
* You are not expected to understand this.
*/
[+] [-] fennecfoxen|12 years ago|reply
That's right. A successful combination of biblical allusion with Dr. Seuss and _Badger Badger Mushroom Mushroom_.
[+] [-] spatulon|12 years ago|reply
A codebase had been maintained by a single person, who then left the company. When the other engineers took over responsibility for the project, they discovered, to their dismay, that it was almost entirely bereft of comments.
Amongst the tens of thousands of lines of code, they found only one comment, preceding an unintuitive bitmask operation:
Nobody could work out what on earth "gok" could mean, let alone why the previous engineer had chosen to leave that comment when they found no reason to comment any other part of the project.Years later, somebody bumped into this chap at a conference and managed to ask him about the project and the significance of "gok."
"Oh, that's easy. It stands for 'god only knows.'".
[+] [-] ColinWright|12 years ago|reply
https://news.ycombinator.com/item?id=555201
https://news.ycombinator.com/item?id=604463
https://news.ycombinator.com/item?id=620595
https://news.ycombinator.com/item?id=1626686
https://news.ycombinator.com/item?id=1699760 (Many comments)
https://news.ycombinator.com/item?id=1805021
https://news.ycombinator.com/item?id=2566782
https://news.ycombinator.com/item?id=2791385
https://news.ycombinator.com/item?id=4838161
https://news.ycombinator.com/item?id=5140016
https://news.ycombinator.com/item?id=5379948
https://news.ycombinator.com/item?id=5978923
https://news.ycombinator.com/item?id=6232500 (Ask HN, not StackOverflow)
[+] [-] kbenson|12 years ago|reply
[+] [-] sanswork|12 years ago|reply
That got awkward fast.
[+] [-] bookface|12 years ago|reply
[+] [-] groovy2shoes|12 years ago|reply
[+] [-] sigil|12 years ago|reply
[+] [-] jpitz|12 years ago|reply
Thoughtful, meaningful, and high-level. I aspire to this.
[+] [-] harrytuttle|12 years ago|reply
All other comments are pointful, well described and useful.
[+] [-] __david__|12 years ago|reply
[+] [-] pilif|12 years ago|reply
When you need more than two lines to explain something, then something is wrong and you'd better fix it.
But maybe the act of writing the comment helps to free the brain to find a better solution.
This happens to me time and time again.
[+] [-] robomartin|12 years ago|reply
Also, if we are talking about embedded there are a lot of comments that are invariant because they might explain details of the hardware interface this particular chunk-o-code might be dealing with. That hardware --external to the chip you are programming-- will not change unless a hardware revision is done, which is far less frequent than code iterations.
[+] [-] 6d0debc071|12 years ago|reply
WHY ORDERS ARE VANISHING
You can't see this from just looking at the code: there are four other systems that interact with the same database. I've managed to localise the problem by the timing of faults, it seems like Cassandra is erasing entries that aren't on its local list.
They won't let us change this because they're afraid of breaking the system.
If Alec's still in charge, you're effectively out of luck. If the boss has changed, try asking about changing it again.
tl-dr: Your princess is in another castle. */
[+] [-] tazjin|12 years ago|reply
[+] [-] adnam|12 years ago|reply
[edit] Yep.
[+] [-] maaaats|12 years ago|reply
[+] [-] m0nty|12 years ago|reply
> question is now closed, I think 528 "answers" is probably enough, no? :) – Jeff Atwood
It is annoying, though, how so many useful SO questions get closed for various reasons when they are just the question I want answered. Perhaps the real problem is Google giving a lot of weight to SO answers, even when they are closed?
[+] [-] idProQuo|12 years ago|reply
I'm glad that StackOverflow leaves closed questions visible. A lot of the value I get from SO comes from opinion-y questions getting answered by experts.
[+] [-] sixothree|12 years ago|reply
Of course it was closed immediately.
[+] [-] bmm6o|12 years ago|reply
[+] [-] ScottBurson|12 years ago|reply
[+] [-] robomartin|12 years ago|reply
It almost seems that there's a generation of programmers being taught that comments are a waste of time. I really don't know where this trend comes from. Lazy? I don't want to believe that.
For my purposes it is a huge negative mark if a programmer is not religious about commenting code. I will not hire someone like that. Why? Developing code is a huge financial investment, yes, but there are other metrics that are far more important than money. If you are doing something non-trivial it often requires a lot of thought, discussion, testing, experimentation, failures, iterations and decisions. Comments within code should be used to document some of this. Document intent, thinking, problem solving approach, corner cases, decisions, where/how it could be improved, performance notes, etc.
This and the code become incredibly valuable. It means that months or years later someone can go back into the code and truly understand what it does, why it does it that way, where it came from and, perhaps, how it could be improved. You don't need to engage in a research project in order to pick-up where the last programmers left of and continue moving forward. In addition to that I firmly believe a well-commented code-base is far more valuable during an acquisition than a thousand files of code with hardly a comment.
I can think of a number of Github projects I've come across with nearly zero comments. What you are looking at is dozens or hundreds of files vomited upon your hard drive that, yes, might perform a useful function at that point in time yet would be a nightmare to dive into to maintain them in any way. Before someone jumps down my throat: Just because something is FOSS it doesn't mean we should not critique such practices. If everyone took the time to thoughtfully document their code the FOSS ecosystem would probably evolve at a faster rate. Some of these packages are so dense they are virtually impenetrable without cubic hours of work deciphering the rats nest of files.
[+] [-] T-hawk|12 years ago|reply
What you describe about the development process, to write down the thinking and edge cases and decisions and such, is important but doesn't really belong in the source code. That stuff belongs in your issue tracker system or the commit messages. What other medium tries to embed a description of the creative process in the work itself? Da Vinci didn't write on the back side of the Mona Lisa the production process for his paints. Tolkien didn't explain how he created the Elvish language in the text of the novels. There's accompanying material for that.
But realistically for software, that accompanying material is not going to get read elsewhere, or survive long-term through migrations to different tools and hosts. So it ends up in the source as the only way to keep it with the code and visible ten years later. Commenting is a least-bad solution, not a good one.
And of course, policies for code commenting never work. You just get scintillating gems like "x+=5; //add 5 to x".
[+] [-] davidcuddeback|12 years ago|reply
That might be true. I had at least one professor who discouraged comments. He said, "I know how to read code." I can understand that in his particular case, he didn't need documentation for higher-level understanding. He taught us the algorithms and data structures being used and he gave us a boiler plate design that we had to conform to. All we had to do was fill in the function bodies and write a main() function.
Unfortunately, it's possible that some students might have adopted that as an overall attitude without recognizing that the context in which it was said invalidated the need for comments for any higher-level understanding. A lot of students looked up to this professor.
That's just a single example. I have no idea how common this is.
[+] [-] VikingCoder|12 years ago|reply
[+] [-] ja27|12 years ago|reply
[+] [-] jgrahamc|12 years ago|reply
Here's a comment from some code that I posted to my blog. The idea was that this would explain in detail to someone reading the code what I was doing with the pieces of a wooden train set. This was critical to the operation of the program and I imagined that many of the readers of the code would need a careful explanation.
It turns out that I'd forgotten what this code does so the comment was helpful.
http://blog.jgc.org/2010/01/more-fun-with-toys-ikea-lillabo-...Interestingly, the first line of this comment contains an error. There are 19 pieces not 15.
[+] [-] eitally|12 years ago|reply
[+] [-] anonymous|12 years ago|reply
[+] [-] moron4hire|12 years ago|reply
[+] [-] _pmf_|12 years ago|reply
[+] [-] wrl|12 years ago|reply
[+] [-] pkulak|12 years ago|reply
[+] [-] peterkelly|12 years ago|reply
- Donald Knuth
[+] [-] auvi|12 years ago|reply
[+] [-] pmiller2|12 years ago|reply