Yegge says that novices don't like his second example. But I've been paid to maintain compilers written in Lisp, by people who've hacked in Lisp for decades, and I don't like it either: The "compressed" code example is not awful, but it's not a good example.<p>An expert should make things clear, even if only to other experts.<p>Basically, that function is too big, and it uses too many mutable variables. I had to stare at the control flow for 'destructuring' and 'init' for over a minute before I convinced myself that it actually worked correctly. More often than not, a deeply nested Lisp function with mutable variables will contain subtle bugs. So when I see something like this, I need to slow way down and take nothing on trust.<p>Here are two ultra-compressed parsers that I like better than Yegge's:<p><a href="https://gist.github.com/1068185" rel="nofollow">https://gist.github.com/1068185</a> and
<a href="http://book.realworldhaskell.org/read/using-parsec.html" rel="nofollow">http://book.realworldhaskell.org/read/using-parsec.html</a><p>To understand these, you'll need some specialized knowledge. But once you understand Yacc (or Parsec), this code is straightforward and clear. The structure of the code mimics the structure of the problem.
My first thought was: "oh my God, I'm a n00b!"<p>My second thought was: "no, I just think I disagree with him".<p>Comments in the code are good. They help the next person that touches that particular part of the project understand <i>why</i> it's coded as is and <i>why</i> it wouldn't be a good idea to code it differently. Commenting a counter increment with "increment the counter" is silly. Commenting it with "it's safe to increment it without taking locks, because the caller already took them" is useful.<p>The most beautiful codebase I've ever seen is PostgreSQL and the comment density in its source tree is quite big. Take a look at <a href="https://github.com/postgres/postgres/blob/master/src/backend/tcop/postgres.c#L789" rel="nofollow">https://github.com/postgres/postgres/blob/master/src/backend...</a><p>Would you say that this code has been written by a two-year-old? Or rather that it's been written by a responsible adult that cared about the integrity of future coders' tonsures and wanted to save them some heavy head-scratching?
Both fail for me.<p>There's a middle ground I aspire to. All I want from code is clarity. Not just for me, but for anyone who has to touch the code in the future.<p>The first is so verbose in comments that you don't see the little code there is. And you couldn't see all the necessary code on the screen.<p>The second (now) is so dense that you have to read the code carefully and slowly to understand what it's doing.<p>I have the luxury of time when writing code, I can consider it and lay it out however I want, comment it how I want. To a person fighting a critical bug they lack this luxury. It's my job when I create code to help the person debugging it (even if it's me) to understand the code as quick as possible so that they may find and solve the problem as soon as possible.<p>Three things I always remember when I code and design software:<p>1) Debugging is harder than writing code, so if you've been clever in writing code you are by definition not clever enough to debug it.<p>2) UNIX philosophy... do one thing well.<p>3) Write both the code and comments in a Hemingway style. Use no obscure language, keep it in layman's terms... but say only what you need to say.
Well, I'm not going to completely dismiss him as a "cranky old dinosaur", but I don't agree with him, and frankly, I find it insulting that he issues a blanket declaration that those with 5-10 years experienced are "crazy teenagers", especially after showing <i></i><i>pretty poorly written representative "good" code of his own</i><i></i>.<p>If I, a developer with 6 years experience, am a "crazy teenager", then he reminds me of a "senile old man". He has a few valid points, but overall, I think his message is unhelpful.<p>I've written the occasional verbose comment before. Why? Well, for context: I was on a 20 person team, working on a poorly designed 750 KLOC codebase for a medical X-ray application. His example of incrementing a counter could have meant the difference between needing to re-shoot (and re-radiate a patient). When we made changes to critical pieces of the code (which were poorly designed before we ever touched it), we had to be <i></i>exceedingly clear<i></i> as to why.<p>While my personal commenting style is more along the lines of his second code example, I see actual code in that function as pretty awful. It's long. It's confusing. The execution path through that code is not immediately clear. Sure, it's dense, but not in a good way.<p>So, the while the author is free to rant, I think he should take a deep, hard look in the mirror before throwing out blanket criticisms of other developers the way he does.
This seems a bit related to some discussions I've been having lately. Bear with me.<p>Really good programmers act as multipliers of other people's productivity. If you can build on code that I write and my code makes you more productive, then that makes my work worth a lot more. If you have to work hard to understand my code, I have failed.<p>But in order for that to happen, not only does my code have to be good enough or do something useful: you have to be able to understand how to make correct use of it. Which means that I have to be able to communicate this to you.<p>This means that it is my job to express myself in a way that maximizes the probability that you will understand how to correctly leverage my code. This is an incredibly hard thing to do.<p>So no, I don't think it is good enough to demand that other people wisen up and develop a tolerance for terseness. This is a somewhat self-centered attitude where the programmer sees himself or herself as the most important. Which is great if you want to do solo projects -- but not useful if you are to allow other programmers to use your talent as an amplifier for their own work and ideas.<p>(Of course, I agree with Steve that comments that read like an entire narrative are excessive. But most programmers fail to document intent and non-obvious quirks. And also, adding vertical whitespace is useful to delineate "paragraphs" of code so one doesn't have to actually <i>read</i> the code, but one can scan the code vertically)
<i>Should a team write for the least common denominator? And if so, exactly how compressed should they make the code? I think the question may be unanswerable.</i><p>I found this point quite interesting. It clearly matters whether the question has an answer and I suspect there's a way to determine that.<p>If we buy into the whole "good programmers are 10x more productive than average programmers", then we can build a mathematical model of team productivity. We have X number of great programmers, Y number of average programmers, and Z number of bad programmers, each of whose productivities are mathematically (in this case, linearly) related. At this point the question becomes an operations research problem which ought to have a clear answer, which might be different depending on your team's configuration. (Question: Are there published, peer-reviewed papers measuring programmer productivity in this manner?)<p>Suppose we don't believe we can actually reasonably compare one person's productivity to another. It then would seem reasonable to try to avoid the question altogether. The issue arises from different skill levels on a particular team, so if you could somehow guarantee people will have the same skill level (at least as it pertains to the specific project) then you no longer need to worry about how to write your code. I think this is what things like pair programming are trying to address - creating a team that is somehow aware of their average skill level and writes code in the appropriate style.<p>This would also explain the general frustration people have with pair programming - if you haven't internalized the team's style, you're likely to either be either way over your head or having to slow yourself down and teach instead of getting as much done as possible.
The narrative commenting style was particularly recognizable. I started out in Java ~8 years ago and only recently moved to Python. Whenever I used to write a particular algorithm in Java I would write comments in the narrative style described by the article. However, I noticed myself deleting large chunks of those comments as I revisited the code at a later point in time. Comment refactoring, so to speak. These days, in Python, I rarely write narratives, and when I do, I delete or shorten the narrative before I commit. Moral of the story: narratives can be useful to organize your brain, even with years of experience, but they should really be gone when the code (and your thought process) is finished.
> <i>If it's a complicated algorithm, a veteran programmer wants to see the whole thing on the screen, which means reducing the number of blank lines and inline comments – especially comments that simply reiterate what the code is doing. </i><p>Don't text editors have, along with syntax highlighting, any "hide comments" and "compress whitespace especially blank lines" features?
RE: "Perl, Python and Ruby fail to attract many Java and C++ programmers because, well, they force you to get stuff done."<p>As a seasoned Ruby programmer, I had the impression that Ruby with its metaprogramming api was just as much a metadata addict's paradise.
I had trouble getting to the conclusions that Steve has drawn here, mostly because I found the article all over the map. In the postscript, he talks about how difficult it was to write it and he actually cut stuff out.<p>I think his intended message would be greatly improved with greater focus. I think he was attempting to draw from disparate things to build a picture of programmers at various stages of growth, but his conclusions read more like a list of general best practices. It was not what I expected as conclusions to the article.
I would like to see a statically typed language with compile time checking of comments. If a comment references a function and the signature later changes, that comment should throw an error at compile time. It would also be nice if a comment, or parts of a comment, could be tethered to pieces of code, so that any modifications to that code will produce a warning indicating you should potentially update the comment.
I am a bit suprised to not see TDD or any of its siblings being pulled into the discussion.<p>To me, the better someone is doing TD, the better the code communicates because TDD makes you think about the right things when coding. It sets your priorities straight.<p>So the question of n00b or vet for me is just how well someone does TDD. And there is also this great book by Kent Beck about Implementation Patterns that is all about well-communication code.
For me personally, stopping to comment on code breaks my concentration on coding. So I usually only do it after I've finished some task, and only at the function level. I don't see a point in explaining why I chose to use a while loop instead of a for loop. The next coder can change it if he/she dislikes the implementation. I would only have denser commenting on some code that I spent a lot of time optimizing for speed.<p>I also have found in full-time and contracting work that your time estimates, or more precisely what the business/client desires your time to be, don't account for commenting, which for me personally can take quite a lot of time if done correctly. If done correctly a comment can convince me to change the code; if you can't easily explain what a function does then it might not need to exist.
I find myself writing narratives, I think part of my own problem is the desire to justify and explain why I'm doing something the way I'm doing it, so at least if I ever have to come back and work with code I wrote a year earlier I'll know what the hell I was thinking when writing it.
I programmed in FORTRAN a lot in the 1970s and Lisp in the 1980s and I had the habit of starting to write new code by just writing entry points and then narrative comments like the ones in Steve's first example (but not so verbose). I would wait a while, do something else, then come back to my outline, and if the narrative outline still made sense, then I would add the code. (I was the only computer programmer in my large company with a private ocean view office, so the technique must have worked :-)<p>I stopped using that coding technique eventually, and Steve's article gives me a good perspective of that transition.
The problem with his 'noob' example is not only that the comments are overly verbose, but also that his variable names are generic and totally useless. 'counter' and 'pos' or 'ref' are so generic that you always have to look at the whole code before you know what's going on. Rename the 'counter' variable to 'bytesProcessed', and rename the 'pos' variable to 'startOfBuffer', and use a variable named 'currentByte' to walk through the buffer... With descriptive variable names many comments become unnecessary.
Any day of the week I'll take reading a comment for a few seconds to trying to get inside the mind of the original coder which can take minutes or hours or days.
I didnt really pay much attention to the points regarding commenting style because it seemed like the real point here was the direction java was going in the late 2000's (or more importantly the ideas being sold). In this context, this posting comes together as very insightful and actually resonates with a lot of truth.
I disagree with Steve's comparison of over-commenting with static typing. The key difference, I think, is that comments are purely for the human, whereas static typing also means something to the compiler. It allows the programmer to offload some work by letting the compiler check it, which comments do not do.
The only rule I have for code style is to write it like a English paper, i.e. to make it easier to read and understand. Yes, I do put blank lines here to there, just to group things together.
All the very best and most experienced programmers (wink) will know ways to write code that both amateurs and elites can enjoy. I personally (wink) do things like extract expressions to give them meaningful identifiers, include units in parameter names, and sprinkle short one-liners throughout to summarize blocks of code.