Catch up on stories from the past week (and beyond) at the Slashdot story archive

 



Forgot your password?
typodupeerror
×
Programming IT Technology

What is Well-Commented Code? 826

WannaBeGeekGirl queries: "What exactly is well-commented code anyway? Can anyone suggest resources with insight into writing better comments and making code more readable? After about six years in the software development industry I've seen my share of other people's code. I seem to spend a lot of time wishing the code had better (sometimes _any_) comments. The comments can be frustrating to me for different reasons: too vague, too specific, incoherent, pointing out the obvious while leaving the non-obvious to my imagination, or just plain incorrect. Poorly or mysteriously named variables and methods can be just as confusing. In a perfect world everyone would follow some sort of coding standards, and hopefully those standards would enforce useful comments. Until then, any suggestions for what you, as a programmer, consider to be good/useful/practical comments? Any suggestions for what to avoid? Also, I usually work with C++ so any resources/comments specific to that language would be too."
This discussion has been archived. No new comments can be posted.

What is Well-Commented Code?

Comments Filter:
  • Code Complete (Score:5, Informative)

    by kimba ( 12893 ) on Monday May 20, 2002 @04:21AM (#3548808)
    I can absolutely recommend a book called Code Complete [amazon.com]. Yes, it is published by Microsoft, but it is an invaluable language-agnostic guide to writing software that includes heavy doses of common sense regarding commenting, coding styles etc.
    • Re:Code Complete (Score:5, Insightful)

      by NewtonsLaw ( 409638 ) on Monday May 20, 2002 @04:44AM (#3548893)
      I can absolutely recommend a book called Code Complete [amazon.com]. Yes, it is published by Microsoft

      Yes, that's on my bookshelf -- but, given the fact that they go to great lengths to point out the importance of checking for buffer over/under-runs and fencepost errors, one can't help wondering if (in the wake of all those critical bugs in IE/Outlook/IIS) any of Microsoft's own programmers have read it.

      More "do as we say, not as we do" from Microsoft?
    • I agree completely, it should be on every programmer's bookshelf. You can hardly call yourself a professional software engineer if you have not read this book.
    • by jsse ( 254124 )
      Yes, it is published by Microsoft

      *Abruptly stops the finger from clicking the link*
    • Code Complete and similar books strikes me as being a bit like books on nutrition and dieting: they tell you what is good for you and they give you some tips on dieting. But most people who read them end up eating junk food anyway because they just don't have the time to do it right.

      By all means, read Code Complete--its suggestions are sensible. But the real culprit when it comes to poor software are time and resource pressures, feature creep, and other environmental factors. Maybe at least the book will let you recognize when your project is doomed and leave; McConnell seems to have done that--he isn't at Microsoft anymore.

    • Re:Code Complete (Score:2, Insightful)

      by Anonymous Coward
      One of the most useful things he explains when it comes to comments is that, if you choose your function and variables names well, you shouldn't need many comments.

      e.g.

      // check to see if whatever is true

      if ( [complex bit of code] ) {
      do something;
      }

      This is much better written like this, without the comment:

      Whatever = [complex bit of code];

      if ( Whatever ) {
      do something;
      }

      He gives lots of examples like this, showing how to write your code so it doesn't need so many comments.

      Great book.

  • I Have to scan through code regularily and the biggest problem is the variable names. I realize that they must mean something to the coder but to us maintainers they're most times akin to Sanskrit. Function(method) comments are nice too.
  • by inflex ( 123318 ) on Monday May 20, 2002 @04:23AM (#3548816) Homepage Journal
    I like to see comments where the function of the next code block is well described in a continuous comment block. Additionally, any further specific comments can be placed at the end, or on top of the lines in question. It's simple enough, and permits comment/documenting-scrapers to produce some potentially useful documentation.


    ie,
    // Foo():infinite loop
    // We attempt to complete an infinite loop
    // here as quickly as possible, in order to
    // remain true to Linus's statements of
    // being able to do them faster with linux.
    while (1) {
    ... // Oooh, this is a fancy line, watch out for it doing nothing.
    }

    • The problem with this is that
      while (1) {...}
      or more commonly
      for (;;) {...}
      is a well known construct for infinite loop. If you turn such a simple construct into six lines of source, then I dread to think how much commenting you'll use when you actually get down to solving the problem in hand.

      for (;;) { // infinite loop
      is far better - it reminds people what you're doing and if someone sees your code and doesn't understand that construct then they know what it does from the comment and they can go and find out how it works and learn it for next time.

      While you're at it, you should probably think about hiring real programmers who know basic constructs in their chosen language...

      • how about while (true) { ?

        1) It reads right in english.
        2) It's type-safe in C++ for -Wall.
        3) It doesn't use antequated or obfuscated C-isms.

        I can't stand things like:
        #define ever ;;
        ...
        for (ever) {

    • by fractaltiger ( 110681 ) on Monday May 20, 2002 @04:44AM (#3548889) Journal
      are the best way to comment it all.

      One day you're commenting on what variables do, the next you try to explain functions, etc.

      I just switched to Java from C++ and neatness is the most important thing I've acquired, not in code per se, but in variable naming. I've gotten used to doingThisWithVariableNames and DoingThisWithClassNames, while keeping THE_CONSTANTS capitalized. Ok, this isn't comments? But you'll be surprised at how much better it is to browse a new language like Java and see the norms of style in it, because old languages use too many confusing double_StandardslikeWritingThis_way.

      Comments go at the top of a page, with the coder's name and date, as well as a small bug report and if you can, a brief function list for those without a visual IDE like JBuilder. You then put a like with PRE: and POST conditions in your code and try to keep one liner comments to a min.

      I learned to comment the end of if structures and function blocks to make the code easier to follow... just add " } //end if" or something.

      Comments should be a paragraph long so that they make some sense. And comments, since they look different from the code sections, should be embelished with ===============, stars, and some
      nice spacing and vertical bars.

      Good comments to me mean good-looking comments, even if they don't have that much substance. Just my 2 cents. They're better than no comments at all.
  • Code Complete by Steve McConnell

    Writing Solid Code by Steve Maguire
  • Per project (Score:2, Insightful)

    by mnordstr ( 472213 )
    I guess the only real solution is to give a specific coding standard for every project. Before you begin coding, make up a standard that every developer has to follow, for comments, code layout, etc.

    A good standard for C++:
    http://www.possibility.com/Cpp/CppCodingStandard.h tml [possibility.com]
  • The practitioner of literate programming [literateprogramming.com] can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other. Donald Knuth. "Literate Programming (1984)" in Literate Programming. CSLI, 1992, pg. 99.
    • Check out Knuth's CWEB [stanford.edu]:


      "CWEB is a version of WEB for documenting C, C++, and Java programs. ... If you are in the software industry and do not use CWEB but your competitors do, your competitors will soon overtake you---and you'll miss out on a lot of fun besides."


      The CWEB page [stanford.edu] also includes example programs, but you will have to run them through CWEB to get the hyperlinked PDF files.

    • Literate programming is to comments what a high level language like Pascal is to assembly language.

      Programmers have the weakness of thinking that they are writing for a compiler. They should be imagining that they are writing for another human reader. This is the essence of literate programming, which is, in my opinion, the only good idea that anyone has ever had about program documentation.

      If the programmer is restricted to interspersing comment lines between lines of code, then the elaboration of the documentation must follow the sequence of the code. To use a simple example, if I write a class definition, then I must declare all the member variables within the block of text that begins "class foo" and ends with "};". However, that may not be the best way to explain the significance of those variables. Maybe it would make more sense (for the human reader) to delay the declaration of a member variable until the place where it is first used. This can easily be done with CWeb. This simple example is hardly sufficient to reveal the power of LP. It is well worth taking a serious look.

      After the literate program is written, it is processed by two other programs. One produces a file suitable for submission to a compiler. The other produces a TeX file, which outputs a properly formatter version to be read by a human.

      The code itself is never the best documentation. It's not documentation at all, except in the most trivial cases.

      Any programmer can write a literate program. It's just a matter of understanding who his audience is.
  • I only work with Perl. When I'm looking at someone else's code all I ask is that they outline the basic function of a particular section of code so when I need to change/enhance/debug something I can find the right area to start looking as quickly as possible.

    I've never had to deal with 'obfuscated' code so I don't know about onscure variables, etc.. or how much more complicating they could be to my task.

    Just point me in the right direction. Anything else is going to be too much or too little... and if I don't already know what the code is supposed to be doing I probably should be talking to someone who does before I sit down to work on the code itself.

    Obviously reverse engineering of software is a whole different beast.

  • Good Comments (Score:4, Insightful)

    by jamieo ( 22197 ) on Monday May 20, 2002 @04:26AM (#3548828) Homepage
    Good code comments should describe the intention of the code. Write them *before* you write the code in a function/method to describe it's purpose. This will make you think exactly what you want it to do, and will allow for others to find/fix bugs easier when the implementation doesn't meet the intention.

    I then write inline comments in the code describing it's flow. It's only then do I actually write the code.

    Comments at file/class level should describe what it does and is used for. It should also describe how it fits in with the big picture of it's packages and the classes around it - give a reader some architectual scope to what they're looking at.

    Get into a habit, even for trivial functions/methods and you'll soon not realized you're doing it.

    Some people say code shouldn't need commenting, and the code itself should be enough. In a perfect world of no bugs and only populated by wizard programmers, this is fine, but not in the world I live in. You write some code and someone else (maybe yourself) will have to debug it at some point - maybe 3-4 years down the line. Even with a "neat" language like Java, working out how things work is much more time consuming without comments.
    • Re:Good Comments (Score:4, Insightful)

      by Cederic ( 9623 ) on Monday May 20, 2002 @08:05AM (#3549361) Journal

      Congrats, you've just described a maintenance nightmare.

      Every time someone has to change some code, you've just forced them to double their workload, and change some comments too.

      If they forget, or don't have time, or are lazy, or don't notice the comment (it's easy to blank them out) then the comment doesn't get updated.

      Now you have a comment that is wrong. And that is so so so much worse than having no comment at all.

      Comment sparsely. Do not sprinkle your code with comments. Especially do not use comments like

      // increment loop counter
      loopCounter++;

      That is adding zero value.

      Inline comments are a major headache - they're painful to write, painful to maintain, and dangerous if they aren't maintained.

      ~Cederic
      • Re:Good Comments (Score:5, Insightful)

        by MadAndy ( 122592 ) on Monday May 20, 2002 @08:33AM (#3549495)
        Changes have to be done twice? That's right, when they change the code, they must change the comment.

        I'll repeat that: they MUST change the comment. And it must make complete sense when they're done or they'll be out of a job!

        Why is this important? When you change the comment, you must think about the comment. You must think about the change you've done and how it fits in with the rest of the code, and what the rest of the code is trying to do. If a comment isn't up to date or doesn't make sense, that's a bug in the code, as bad as any other, and it needs to be fixed.

        It's not difficult to spot when the comments don't line up, so they're fairly easy to fix. While you're there fixing the comments you need to check the code, 'cos whoever the idiot was that wrote it, they obviously haven't checked it properly. Go and hit them with a Very Big Stick.

        Certainly you shouldn't whine about the extra typing. A little extra typing shouldn't hurt - and you should be able to type faster than you can think, so it shouldn't really slow you down. If it does, go take a typing class.

        And if your lame excuse is that you're in too much of a hurry to maintain comments, just make sure you're not in too much of a hurry to deal with the bug reports that come back because you haven't checked your code properly.

        • One of the great insights of the Agile Software Development movement, if you ask me, is the realization that a process which doesn't take into account the strengths and weaknesses of the people who will use it is flawed.

          So, it's one thing to say "if they change the code, they MUST change the comments", but realize that unless you have the ability to force the issue (a tool to make you change comments before saving changes, managers who care more about firing programmers who don't follow code standards than avoiding schedule slippage -- hint: I've never seen one of these, EVER), 9 times out of 10, they just won't do it. It's like teaching abstinance as a method of reducing teen pregnancy.

          Thus, the practice of having comments which are redundant w/ the code is simply setting the project up for failure as the parent poster pointed out.

      • Re:Good Comments (Score:4, Insightful)

        by Simon Brooke ( 45012 ) <stillyet@googlemail.com> on Monday May 20, 2002 @08:53AM (#3549605) Homepage Journal
        Every time someone has to change some code, you've just forced them to double their workload, and change some comments too... Inline comments are a major headache - they're painful to write, painful to maintain, and dangerous if they aren't maintained.

        ... and absolutely essential to the poor bastard who comes after you - without them he has zero chance. I spent some hours on the phone a couple of days ago talking some poor lad in the states through the trickier bits of one of my open source packages. Fortunately it is inline-commented, so I at least knew what I had been intending to do.

        I agree with everything you say about the nuisance of maintaining comments, and I agree with everything you say about the problems that happen when you fail adequately to maintain comments. It's a chore; but it's a vital chore. It's got to be done.

      • by Pollux ( 102520 ) <speter@[ ]ata.net.eg ['ted' in gap]> on Monday May 20, 2002 @11:19AM (#3550805) Journal
        ...who make reviewers like me stare at computer screens for endless hours trying to figure out how the hell your computer code is supposed to work.

        Comment sparsely. Do not sprinkle your code with comments. Especially do not use comments like

        Yea, I can already picture your programming style. You'd make a 200-line function with the only comment being " // Creates hash table ". Question: Where does that leave me? When I find out that there's some problem in the hash algorithm, I have to dig through 200 lines of code to find some freakin' bug that is described only by "Creates hash table." Your example of why comments don't need to be made is a poor one:

        // increment loop counter
        loopCounter++;


        That is adding zero value.

        Yes, because it's one line of code, and the code is described through the variable. But when sifting through lines of code, you often find beautiful works like iHateMyJob++; or fuckMyBoss--; to name a few. And needless to say, they're uncommented in the code. Until computer code can be written bug free in complete English sentences (aka Never), the rest of your team of workers needs to understand what your code does.

        Personally, I make sure every function says what goes into it, what comes out of it, and what setup (variables, etc.) need to be made for it to be called. I do not comment every single line of code, but I do make sure that every line is accounted for by descriptive sentences, explaining the task that I wish to accomplish as well as what variables / registers / actions I take to accomplish the task.

        Every time someone has to change some code, you've just forced them to double their workload, and change some comments too.

        Okay, this just pisses me off. You didn't mean what you said. Here's what you meant to say:

        Every time I have to change some code, you've just forced me to double my workload, and change some comments too.

        I can assure you, from a reviewer's point of view, comments SAVE my time from trying to understand what each piece of code is trying to accomplish. Commented code may make you work extra time to detail the lines of code (I do admit, some programmers are quite tallented at keeping track of every single line of code in their head as they work on it on the computer), but it saves tremendous amounts of time once that chunk of code needs to be integrated with other chunks of code into the final product.
      • Re:Good Comments (Score:3, Interesting)

        by jamieo ( 22197 )
        I agree with the "increment loop counter" comment, that isn't worthwhile at all - but that's the difference between good and bad comments ;)

        However, I completely disagree with your premise about this being a maintenance nightmare and doubling workload.

        It's the exact opposite of a maintenance nightmare - it helps maintenance (certainly for long running large projects with developer turnover).

        It's also very little overhead. If you are a professional developer, just count how many hours you really write code in a week of working. It's not a great deal really, and the added time to add good comments is very little. The rewards of doing it are far greater than any costs.

        This is a complete mindset thing, just like coding standards - if you get in the mindset, it's easy and no cost, if you moan and complain and fight them all the time it's a pain and loads of work.
      • Re:Good Comments (Score:3, Insightful)

        by ClarkEvans ( 102211 )
        Congrats, you've just described a maintenance nightmare. Every time someone has to change some code, you've just forced them to double their workload, and change some comments too.

        The comments should talk about _what_ the module dues, not _how_ it does it. Stick with this distinction and it'll be a bit easier. If your module changes so much that the _what_ changes... then you really should take the time to reconsider your comments... as they may point out what assumptions other code may be making and where compensating changes may be needed.
      • Functions should have their arguments documented-- what they mean and what they do, and their return values documented. That is sufficient.

        Inline comments have a place, but they are way over used. If you are telling me how your program works using inline comments, I will ignore those comments becuase if there is a problem, your code may not behave as advertized.

        Instead inline comments should document WHY you do something a certain way and help me to understand what problems caused a particular piece of code to us a particularly clumsy algorythm or why a seeminly extranious bit of code was added. Don't tell me how-- that is what the code is for.

        And use whitespace as your friend to break things up into logical chunks which are easily readable and logically connected. This is the reason for indenting your code, but the same principle can be used by adding additional line breaks to separate logical chunks of code (this makes more sense then meaninglessly breaking up functions).

        I think that these are relatively language independent advice. I use it in Perl and PHP, and when I read C and C++, I appreciate these tips as well.
  • I use doxygen++ for C++; it's great

    about 1/4 of my lines are comments -- most all of which are incorporated into doxygen descriptions -- and the rest only appear in the sourse listings

    see http://www.doxygen.org/

    • Agreed - the best form of commenting is peer-reviewed
      JavaDoc or Doxygen. I've used both and used to love
      Doxygen, it's superbly flexible and easy to use.

      It helps to gather up the real things people should be commenting; pre-conditions, post-conditions etc
      and not "Infinite loop".

      Plus it looks nice presenting your docs on a
      website as part of the nightly build, or printed
      out as a (huge) pdf book. All for no hassle.
  • by oingoboingo ( 179159 ) on Monday May 20, 2002 @04:27AM (#3548831)
    Well commented code should definitely contain a liberal smattering of four-letter expletives, eg:


    // no fucking idea how this works
    obj.doMagic();


    or...


    //bet those fucking lazy cunts in the QA team don't pick this up
    fileSystem.delete();


    When your code is released as open source and becomes famous, people can amuse themselves by searching through the source code to find all the hidden expletives, sort of like easter eggs. If you work for a commercial organisation, you can sit back and enjoy the panic as the QA and release teams sweat it out trying to track down every last filthy utterance before shipping to a fucker...errr..customer.
    • My favorite is:

      //fucking piss drunk... not sure why this works, but will fix later.
    • Well the linux kernel certainly qualifies then...

      [admin@frodo linux-2.4.9-31]# grep -r [Ff][us]ck * | wc
      134 1327 10723
      Detection of the other expletives is left as an exercise for the reader...
    • by Anonymous Coward on Monday May 20, 2002 @06:09AM (#3549089)
      Until someone runs nm on your executable and finds some "funny" variable names.
      Funny variable names are sometimes related to say specific bugfixes a certain individual or customer has demanded.

      I know one person where very large customer demanded a specific and very idiotic new feature to the software, due to the customer being an idiot.

      Executable was not stripped.

      The variable name to control this feature in certain functions was thus called IsAFuckingIdiot .

      Customer by convention always ran nm on all new executables they installed.

      Customer got very upset.

  • Doxygen, etc (Score:5, Informative)

    by Stary ( 151493 ) <stary@novasphere.net> on Monday May 20, 2002 @04:29AM (#3548836) Homepage Journal
    Tools like javadoc, or maybe better in your case doxygen [stack.nl] can really help when it comes to commenting code... the idea is pretty much that you place a documentation comment before each function, or class, and so on, which usually makes the entire thing much easier. Having done that, I've found that only a few more non-obvious parts have to be commented within the actual functions.
  • I also have seen my share of other people's code.
    Quality of comments varies.
    I've seen code from the 'hardcore hacker', who believes that the statements themselves suffice as comments - 'the code is intuitively obvious, and it comments itself'.
    I've also seen code from complete lamers, who dilute the code terribly with irrelevant shit:

    i++; // increment i

    Over the years, I've noticed that composition of code, and commenting/documentation of code, tend to draw on two different parts of the brain.
    Often, I find myself in a 'zone', where the code flows freely, and where commenting code feels like a total distraction.
    Other times - for instance, when I'm hunting an elusive bug, I find a different part of the brain kicking in - and at that stage, I find it easier, even pleasurable, to add meaningful comments, to change indenting, variable names etc, as if I'm narrating the code to someone else.
    I guess it's a matter of balance, and using the right mental faculties at the right time.
    A good rule of thumb is to imagine that someone else is sitting beside you, someone less acquainted with the task than yourself (eg a non-technical manager). Imagine you're explaining to him/her how the code works, and put these explanations in the code as succinct yet clear comments. Imagine this person asking you, 'what's that variable'. Don't be afraid of global search'n'replace of identifier names across all the applicable files. And imagine this person sometimes getting up and leaving you in peace, so you can have those precious moments to hack to your heart's content.
    In conclusion, I feel that much of a person's personality can be read from one's code. Is someone fundamentally easygoing and helpful, and caring about others? Or is someone a complete egotist, emotionally shut down almost to the point of autism? In my mind, the ability of code to communicate its intent and methods to other programmers is almost as important as the code successfully performing its task, since its communicability directly affects the ability and interest of others in working on it, and thus its openness to manpower leverage.
  • by NewtonsLaw ( 409638 ) on Monday May 20, 2002 @04:34AM (#3548857)
    It's been quite a while since I wrote any significant amount of code but after spending far too many years cutting code too early in the development process I eventually woke up to the fact that coding is the *last* thing you do (apart from testing and debugging that is).

    First-up you need a good spec -- and the spec should include the user-interface details to the extent that you could actually write the user-manual from that spec.

    Indeed -- if you can't write the user-manual from the spec then the spec is incomplete.

    From the spec the programmer should develop the structure of the code in another document.

    That structure document is repeatedly refined in a top-down process until you (eventually) reach a point where you're actually cutting code.

    I was always surprised just how much easier it was when the code was written as the lowest level of the structure documentation.

    Not only could you comment out the program structure document so that the compiler would ignore it -- but you ended up with absolutely accurate and comprehensive documentation built into that source.

    Project managers love this technique (and when I was in a project management role I demanded it of my team) -- it ensures that technical and end-user documentation are no longer the bits that get left until last and thus are either very shoddily thrown together or, if the project goes really over-budget, not produced at all.

    Of course, as we all know, there's a huge amount of temptation to just leap into coding at the earliest possible stage and leave the documentation until later -- because some stupid managers use number of code-lines completed as a metric of project performance -- duh!

    If you're smart and use good tools you can selectively collapse and expand the in-source documentation so that when you're trying to get familiar with a module that someone else has written, you can descend down the structure tree one level at a time without the meaning being diluted by stuff that is at a lower level.

    Unlike the days of interpreted BASIC, there's very little overhead involved in integrating documentation and code these days -- so there's no excuse not to do it.

    If required, the documentation can be automatically extracted from the source -- but by keeping the master copy in the code it becomes easier to ensure synchronization as changes and updates are made during the lifecycle of the project.
    • This is a technique I hope to follow with a few "personal" projects that I'm about to start. I'm refusing to write any code until I get down at least a spec for what each section is supposed to be doing.

      Alas, since the UI is wholly divorced from the back-end (I discovered I'd designed in my head an n-tier system just by seeing what I hated about both similar and unrelated software I've been forced to work with), I'm not sure I could follow everything precisely the way you suggest. After all, in the overall design, there will actually be several clients, each displaying data appropriate to its interface (web vs. fat client vs. text vs. scripted API vs. ???). I know what I can, and in fact must, do is define just how the "back end" (in terms of the clients) tells the clients what to display, what to get from the user, etc.

      I've also got to point out that in the past, I've been guilty of the "jump right in and code immediately" method of development. Unfortunately, I didn't have much in the way of control, since we were under pressure from both upper management and the customer (they have a lot of boats and guns...) to produce code for testing immediately.

      Even though this was for a "next generation" of a system already in place, it was a complete rewrite in a language the customer wasn't all that familiar with (C++), and so they were concerned that we wouldn't be able to guarantee anything would even work, let alone within the tight timing constraints required by parts of the overall system that weren't being changed.

      We had to deal with collecting all sorts of assinine metrics, such as the SLOC (Source Lines of Code) you've mentioned. Of course, the number of comments was also a metric that needed to be collected, and so we somehow had to find time to do those while frantically trying to keep pace with specs that seemed to change arbitrarily on a weekly or monthly schedule. Assinine? Yes. Real life? Yes. The only saving graces were that we'd managed to convince everyone who made decisions that some ridiculously low SLOC count was what we were responsible for in terms of monthly performance (giving us some breathing room to do intelligent design), and regular (weekly) code reviews amongst all the developers, spec writers, and the customer, to verify that what we were doing was, in fact, correct. (Though it seemed at times that we spent the majority of the meetings teaching all of the non-developers how to code in C++)

    • Yes, we can tell it's been quite a while.

      Right now, businesses go to their IT teams and say "We need software that does X. Deliver it in 8 weeks."

      It would take 8 weeks to write a structure document in the manner you are describing (especially going through the various top-down iterations to reach code).

      Instead we have to write the basic framework of the solution, get that ready in four weeks, and then change and tweak all the little pieces of functionality that have changed in the requirements since we started. Because businesses don't know what they want, and all that is definite is the go live date (usually because the Marketing team have a fixed launch date)

      How are you meant to pre-document a requirement that arrives three days before go-live? With a suitable methodology you can add it, test it, and regression test the rest of the system to be sure you haven't broken it. But then generating user documentation too? Dream on, that's going to have to wait.

      ~Cederic
      • Well, it sort of depends on what kind of code you're writing, doesn't it? In applications development, the dev cycle can be 1 year long or longer, with support cycles that run about 3 to 6 months.

        In web development, your dev cycle is often 3 months or fewer, with support cycles measured in days or even hours. The practice of shifting requirements up until the ship date is one that we, as professionals, have a duty to curb. If you're implementing new requirements during the final 10% of the project, then you're allowing the customer to break the project and blame you.

        Unfortunately, the nature of programming doesn't really change between those extremes: it's still a question of figuring out what the problem (the product requirements) is, designing a solution to the problem (writing a spec and, hopefully, designing it so that three cycles from now when you get a requirement to change the product, you can), and then writing the code that implements the design.

        The comments we always see in these discussions along the lines of, "comments are for the weak; real programmers don't use comments..." don't take into consideration the fact that the odds are very good that you won't be supporting your own code in a year, you'll be dealing with someone else's crap. As professionals, it behooves us to provide as many clues as we can to the poor sods who'll follow after us -- because what goes around, comes around.

        When I'm doing really fast web development, the spec is often a drawing on a white board -- so I take a picture. The design is often a doodle in a notebook -- which I label and keep on my bookshelf. And when I start banging out code, the first thing I do is pseudocode in comments, then interleave the real thing. That way, when I'm interrupted in the process, I can pick up again quite easily.

        I've handed off a lot of code to other people, and I've never gotten any complaints about too many comments (or about useless ones). I have gotten comments about how easy it is to follow what I'm doing, and that's enough. Do what you need to do to get the job done, but keep in mind that the job doesn't stop with getting the thing to compile and link.


    • That style of programming leads to unreadable and unmaintainable code. The problem is that, in many cases, the programmer that required reams of documentation in order to write the code also requires that documentation in order to read it. The system-level become inappropriate to the evironment and language being used since the design was done "in your head" instead of "in the code.

      IMHO, detailed specs should only be done when there can be a GAURANTEE that it won't change for at least 2 years. The is is the usually the case with specs produced by groups like W3C, IETF, or the OMG, and a lot of programmers think they should copy the activities of these beauricratic organizations in their own work, where requirements can be expected to change continuously. In this environment, maintaining a detailed specification that is separate from the code is far too impractical. It's better that programmers make the code and the focus of their attention and make sure their code *deserves* to be the focus of attention (i.e. it's well written, elegant, easy on the eyes and mind, fun to take walks on the beach with, etc...).

      -n00m
    • What you are describing (and quite well) is the top-down programming practice. There's a big problem with it, though: in the real world, things change. As others have pointed out, you can't be guarenteed to be able to hammer down a specification that will be satisfactory for a year, or a month, sometimes even a week or a day. Some customer, some manager, or whoever, will demand a change in the final product. What will you do then? You will have to change your entire structure around and that can be extremely difficult.

      Fortunately there are other ways of approaching the problem. One of them is called the bottom-up approach. The basic idea is to create a mini-language that one can better formulate your problem in, and then start putting the pieces together. This is complimented by dynamic semantics that languages such as Common Lisp or Smalltalk have. Incremental, interactive compilation and development is well supported by these environments. The code winds up being self-documenting because you wrote it in a mini-language! Weirdly obfuscated--but necessary--as well as commonly used pieces of code can be abstracted with Lisp macros. Changing your data-structures is no problem, already in-use data-structures can be dynamically updated (and you can control how it happens). Errors are handled by the exceptional condition system (no pun intended) and the program can be continued from where you left off, after being fixed. Always you have a working, running codebase.

  • by IvyMike ( 178408 ) on Monday May 20, 2002 @04:41AM (#3548878)

    Take a look at this function, and tell me if there's a bug:

    void foo(void) {
    int* x = 0;
    int y = *x;
    }

    Easy, the bug's the SEGV, right? Take a look at the same function, this time with comments:

    // Function: cause_segv
    // Description: Causes a SEGV for testing purposes
    void cause_segv(void) {
    int* x = 0;
    int y = *x;
    }

    The point? A bug is unwanted behaviorm, but that only makes sense if you've defined what the correct behavior is. My example is trivial, but often this is a real concern. Function "bar(int,int)" returns null whenever one of the arguments is negative--is that a bug or a feature? Your function has a goal in life, a contractual obligation to do something; make sure it's clear what that something is.

    Note that if you choose good function and good variable names, a simple one or two line comment at the beginning is usually sufficient to document whe function's intended behavior.

    I also find that an "assert()" or two on the arguments at the top of the function makes it clear what values the function accepts, and which one the function doesn't handle. It's an easy way to document the contractual obligations of the function.

    Stuff not to put in comments is stuff that's easily devised from the code. Check this out:

    // Function: square
    // Inputs: int x
    // Outputs: int
    // Used by: pythagorean(int,int)
    // Description: returns x squared
    int square(int x) { return x*x; }

    Did the "Inputs" or "Outputs" add any value? That information appears again, two lines below in the function definition, and it's guaranteed to be correct there (unlike the comment which will be out-of-date and wrong when we change "square" to work on longs). The "Used by" might have added some value, if it was correct, but as it turns out it's out of date, and 15 other functions now use "square". Any information better derived looking at the code should be left off. Any information which can be better found using "grep" or "find in files" should be left off. Any information that will probably be out of date at some point should be left off. Heck, in this situation even the description is probably extra verbiage, since it doesn't really help anyone. (I'd probably put it in out of habit anyway, though...so sue me:)

  • Examples.. (Score:5, Funny)

    by popeyethesailor ( 325796 ) on Monday May 20, 2002 @04:42AM (#3548881)
    # all of these will also get moved elsewhere

    # this is the worst damned warning ever, so SHUT UP ALREADY!

    # Keep your friends close but your enemies closer.
    # Or ignore them, we don't care.

    # You know, we do assume comments are linear -Brian
    Refer here [slashcode.com] for further details:)
  • comes this advice:

    Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to
    write the code so that the _working_ is obvious, and it's a waste of time to explain badly written code.

    Generally, you want your comments to tell WHAT your code does, not HOW. Also, try to avoid putting comments inside a function body: if the
    function is so complex that you need to separately comment parts of it, you should probably go back to chapter 4 for a while. You can make small comments to note or warn about something particularly clever (or ugly), but try to avoid excess. Instead, put the comments at the head
    of the function, telling people what it does, and possibly WHY it does it.


  • PDL it is good no? (Score:3, Interesting)

    by ZanshinWedge ( 193324 ) on Monday May 20, 2002 @04:44AM (#3548890)
    Personally, I like documenting backwards. Start with the requirements, work to the architecture, then get into writing PDL (Program Design Language). Essentially, you write out as detailed instructions on what the routine does as you can, without getting to the nitty gritty. It describes the intent of the code, not the code itself. It morphs into excellent comments when you expand it out into full code, and it also has the nice little advantage that it's at a high enough level that it's applicable to multiple languages (if you should desire to switch).
  • by jon_c ( 100593 ) on Monday May 20, 2002 @04:48AM (#3548906) Homepage
    Personally I think the linux kernel is very well documented, at least the scheduling part, which is what I've looked at. Linus has a style of inserting huge comment blocks that explain exactly what's going on, then he'll have a page of code that does it, with little or no comments.

    A style suggested in Code Complete (I forget what they call it) is to write a method completely in pseudo code, make sure it's correct, then insert the actual programming code under each line of pseudo code. This technique, while clever I find leads to many useless comments like "loop through the employee records" and "increment the counter".

    A good test to see if the comments are working is through a code review, people will very often not know what's going on, or point out confusing comments or code that needs a better explanation. Code Reviews really improves your idea of what good comments are and teaches you what works and what doesn't.
  • Good commenting (Score:3, Insightful)

    by RockyJSquirel ( 412960 ) on Monday May 20, 2002 @04:55AM (#3548925)
    I wish I had time to go into more detail but I recommend:

    1. Every class should have a clearly defined public interface and documentation of:
    a) what the class is for and (if appropriate) why it was designed the way it was
    b) how it works
    c) how to use it
    d) how to extend it (if there's any reason to do so)
    e) it's lifetime / memory usage(if appropriate)
    f) if it's tightly connected to any other classes or functions, that should be documented
    g) how to make classes derived from it (if appropriate)

    2. Every function should have a comment that says:
    a) what it does
    b) why (if there's any question)
    c) what side effects it has (if any)
    d) what side effects it depends on (if any)
    e) if the functions is tightly bound to any parts of the program (it's not a context free sort of routine) then you should list where it's called from.
    f) examples of how its used (if appropriate)
    g) This one is important: describe the algorithm. It's important to keep this sort of comment up to date.

    I'm not so enthusiastic about comments on individual lines of code. They seem less necessary to me than the other sorts of comments, especially if everything is well named.

    I've been trying to get people at my latest company interested in code documentation, but I seem to have lost that battle. It's a shame. The only way to develop around here is to read every damn line of code, and that's unbelievably wasteful.

    Rocky J. Squirrel
  • It's real simple. If the reader can't tell what the code does from reading it, either it's written badly, or the reader is incompetent. In either case, comments won't help. If I see too many obvious comments, it's a clue that the author was clueless and I should probably just throw the code away because it will cause more trouble than it fixes.

    When comments are useful is to fill in information that is obvious to the author but not obvious to anyone else reading the code. When the author wrote the class/function he knew why he was doing it, why the function was needed at all, this kind of information allows a new developer to get an overall understanding of the project much faster.
  • code comments (Score:2, Insightful)

    by VonKruel ( 40638 )

    If the code is well structured, variables, classes, methods, etc. well-named and well-conceived, it will explain itself to a large degree, and won't require an English play-by-play of every friggin detail. Generally, it's a good idea to have high-level comments that say "this chunk of code does X", but lower-level comments are often a waste of time, and only serve to clutter the code. Having said that, sometimes code is unavoidably hairy, and you have to recognize cases where the code needs some lower-level explanation, and provide it. First, avoid complexity, failing that, manage it. Generally speaking, I think code comments serve the purpose of helping s/w people to develop a mental map of the code. Code should have as few comments as possible, but no fewer :-)

  • I explain what each function is supposed to do, along with any assumptions I'm making and any desired side-effects that the coder should expect. If I'm using algorithms beyond a basic for loop, I'll stick pseudo code with example inputs and outputs in the comments as well.

    Function and variable names that make sense go without saying - they may be a pain to type in, but in the end they don't hamper code efficency, so make them as self-explanatory as possible (with exceptions like using i and j for a 5 line for loop.) Remember, whitespace and good, CONSISTENT formatting is just as important as good commenting. Funky, inconsistent formatting pisses me off just as badly as cryptic commenting and 6-character all-capital variable and function names.

    I comment under the assumption that the next time I look at this code, it will be years later and I'll have forgotten much of the programming language I originally wrote the code in (basically, I assume the next time I look at the code, I'll need to port it.) In instances like this, basic descriptions of what a function is supposed to do, along with pseudocode of the alogrithm with sample inputs and outputs are EXACTLY what I need - not to mention, they serve as a road map for when I'm writing and debugging the code the first time. Typically, I'll have just as much commenting as actual code for simple stuff, for anything beyond that I'll have double as much commenting as code (readable english is less efficient than clean code, so what do you expect?)

    You should always look over and polish both your code and your comments before you shelve your code. If you're leading a team, it should be your code that sets the bar for good logic, commenting and formatting style. Even if you're not, good maintainable code is what they're paying you do write (I hope.) Of course, if they aren't paying you enough to write clean, commented code, then they get what they're paying for...
  • I thought that commenting was only supported to prevent a block of code from being compiled (or even better, dozens of little fragments of code).

    What is all this about using comments to document what you are doing?
    • Nah, that's what if statement blocks with conditions that never will be met are for. That way you preserve the bulk of your unused code when you compile your binary, so you can bloat your release and have it shipped on a couple of CDs. Not to mention it confuses the hell out of the Q&A guys.
  • On a large project a key to getting anything done right is to have a standard and check that people stick to it. Code reviews are a Good Thing in any case. Checking that the comments say useful stuff should be part of this.

    Every file should start with a preamble giving module name, version, author, and maybe revision history. Most of this can be generated automatically by your version control system.

    Then there should be anything from a few sentences to a few paragraphs saying what problem this module solves and how it does it. Refer to any other documentation (e.g. UML diagrams, textbook for the algorithm) that might help illuminate what is going on.

    Each function or data structure should have a similar comment explaining what it does.

    Avoid comments that say "this routine is used by the Foo Function to update the Bar structure". Instead just say "This routine updates the Bar structure such that...". If the routine makes no sense on its own then it probably shouldn't be on its own.

    Paul.

  • Such words of wisdom as I've been able to muster in two decades of experience:

    Comments are vital, but like all programming tools require judicious use to be effective.

    It is easy for large comments to fall out of sync. with the code, so large comments should generally be reserved for high-level documentation of the kind one would expect to find in a literate program. Prefer a pointer (say, a URL) to a document explaining an algorithm than a block of text explaining the algorithm.

    Brief comments on types and data constructors are vital where their use is not obvious. The same goes for functions, methods and procedures.

    Function bodies should be small: it is better to have several small, easily understood functions (with names that clearly convey what they do) than one large block of code.

    Use of formal language in comments keeps them short and clear. Compare the following:
    • take(N, Xs) is the first min(N, length(Xs)) members of the list Xs;

    • take(N, Xs) returns the first N members of the list Xs or the entire list if there are fewer than N members of Xs.


    The term 'list' can be omitted if the function has an explicit type signature (even if your language is untyped, specifying types somewhere is invaluable documentation.) Another point to note is that these comments make clear what happens when N > length(Xs) - you should specify what happens in all circumstances, even if that just means saying "if these conditions are not met then the behaviour is unspecified."

    Including sanity checks in code is a useful alternative to documentation.

    It is a very good idea to annotate code with the invariants that should obtain at key points.

    Eschew clever code. Nobody will be impressed and it's a maintenance nightmare. And you'd better be very sure you got it right...

    Don't cut corners. Include *all* the error checks. Learning how to write elegant robust code is what distinguishes real programmers from cowboys. Managing both is an acquired skill.

    Avoid globals. Seriously.

    State and mutable update lead to unreusability, bugs, madness and divorce. Learn a functional programming language (add smiley if that helps).

    Someone once said words to the effect that if you find yourself writing a bulky comment, ask yourself if you could restructure your code so as to make the comment unnecessary.

    - Ralph
  • I work in a coding shop where our company coding standard insists on some microsoft plot called 'Hungarian Notation'.

    For the unitiated, this means that all variable names have to be prefixed with letters that indicate it's type. i for int, f for float, ch for char, etc.

    The linux CodingStyle file (in the Documentation directory in every kernel source kit since who knows when) slates hungarian notation thus:
    Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged - the compiler knows the types anyway and can check those, and it only confuses the programmer. No wonder MicroSoft makes buggy programs.

    If you don't have Linux kernel sources on your machine, you can get a copy of CodingStyle here [linuxhq.com] (from the 2.0 kernels).

    As a result of all this mucking about, because I tend to look after most of the dynamic memory, linked lists, and low level bit and byte-bashing operations, I end up with variable names with more prefix letters than letters in the name. I really detest this coding standard (which for some reason also forbids the underscore character on the grounds that it looks like a minus. Do you get foo_bar and foo - bar confused? I don't.

    I don't agree with all parts of the Linux CodingStyle, especially the bit about brace placement, but it's a good starting point for any C coding standard. Unfortunately, ours was designed by microsoft-centric folk who think that // is the start of a comment.

    Ayhow, back to topic, the Linux CodingStyle also contains the distilled wisdom:

    Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to write the code so that the _working_ is obvious, and it's a waste of time to explain badly written code.
  • See: How To Write Unmaintainable Code by Roedy Green [mindprod.com]

    Every time I read it, I laugh from all the crazy examples of how not to do things:

    eg:

    16: Names From Mathematics:
    Choose variable names that masquerade as mathematical operators, e.g.:
    openParen = (slash + asterix) / equals;

  • by Bazzargh ( 39195 ) on Monday May 20, 2002 @05:18AM (#3548992)
    This has come up before - in Martin Fowler's book, "Refactoring", he makes the controversial claim that sometimes comments are indicative of a need to change the code.

    Consider the different types of comment:
    - boilerplate comment at the top of a file: helps noone but lawyers.
    - change history comment: better use your source control tool to maintain this.
    - comment before a class: does this mean the class is badly named, or too complex?
    - comment before a method: ditto.
    - comment inside a method: could be a smaller method screaming to get out.
    Also heavily commented code is quite commonly just explaining away stupid code tricks.

    Nobody's suggesting that all comments are bad, just that a lot of the time adding comments is a poor substitute for fixing whats wrong with the code. Of course sometimes its the language thats the problem :)

    -Baz

  • A couple of words, OCL

    This is in the interface, rather than an implementation, and you won't get the code to the impl, so what does it do ?

    /**
    * Get the Bug description for the given Id
    * @pre id must be > 0 and less than BugList.lastId(), the highest bug number
    * @post The return must not be null
    * @invariant does not change the number of bugs
    */

    Well that is the comment block, not all of it because there is some OCL in there, but I thought I'd leave something for Google. The point is that the description describes exactly what the method does, it also says what the caller must do or face the consequences, and what the caller can rely upon when the method returns.

    And for any one who says comments aren't required if you write the code well enough... you are a muppet. Interaction via interfaces is a basic tennent of coding, .h files anyone ? You shouldn't have to look at the code.

  • It is not only executeable code that can benefit from comments. In particular any numeric fields should have a units comment (e.g. m or m/S). It can be quite time consuming to deduce the units from the code.
  • 1. Adopt some set of coding conventions. For instance, always return 0 on success/in the normal case.

    2. Use informative variable and functionnames. Short names are preferred, but make sure it's clear what you mean. If it's impractical to fit all the required info into the var- or functionname, add a comment explaining the intended purpose of the variable/function.

    3. Use small functions! Split actions up into logical steps. In combination with 2 this will help make your code a lot more readable, removing the need for many comments. Like Linus says: "The maximum length of a function is inversely proportional to the complexity and indentation level of that function."

    4. Document any abnormal behaviour. For instance, if you've adopted the convention that functions return -1 on errors and you have a function that differentiates between different errors by returning either -1 or -2, document what the abnormal return values mean.

    5. If the overall purpose of a group of functions (e.g. in one sourcefile) isn't obvious, add a general comment that explains the big picture. Code is much more readable if you know what it's trying to do.
  • by Daetrin ( 576516 )
    I recently ran into two functions in the code base I'm using that were titled "ObjectTrackDirection" and "ObjectTrackToDirection". The similarity in names was annoying, but the criminal part was that neither function had comments indicating what they did, or what the difference between the two was. In fact, the only comment in either section of code was on one line that was duplicated in both pieces of code, and which said "not sure why this is needed". This did not give me a great deal of confidence as I started out trying to decipher what exactly these functions were supposed to accomplish differently.

    No matter how clear you think you made the name of the function, there should be a comment explaining what the fuction is supposed to be doing. If the function accepts a lot of flags or variables you should briefly explain what they're each used for.

    Knowing what the function is supposed to accomplish is a big step forward, even if there are no other comments at all.

    If you're still willing to keep at it, start commenting the big blocks of code in the same manner. What are you trying to do with this loop? Why are you testing for these cases in this if statement, and if it succeeds, what are you trying to do inside of it?

    Always go in favor of more comments. I would rather have to skim by a dozen comments that I don't need to read than be left hanging for the lack of one comment when something goes wrong.

    And finally, always use whatever comment system your source control program uses! Even if it's just "I did some stuff to fix some problems with A," because if I later find out that a particular case of A is broken, I don't want to have to do a diff on every single code change made since the last time I knew that case of A worked.

  • by bentini ( 161979 ) on Monday May 20, 2002 @05:42AM (#3549037)
    I personally despise comments such as:

    i++; //increments the variable i

    I think that they are unclear and do not properly explain the situation. Remember, you're writing so people can UNDERSTAND the code, not so that you can impress them with how smart you are. Instead, strive for a comment like this:

    i++; /*changes the value stored in the space referred to by i to be the sum of the old value stored in the space referred to by i and the constant 1. Note: In C, this may cause what is known as a "silent overflow" if the value is too large, and go so far as to make a large positive value into a larger negative one. Oh my!

    This way, people who read your code not only understand your program, but all programs. I really think that each function you write should repeat a semester's worth of computer science theory and programming practice, so that anyone who reads your code will learn from it. Remember, not everyone knows idioms, and why should they? And since we all write open source on slashdot, many novices are going to have their introduction to any computing environment by looking at the code you write at any point.

    Your most humble and obedient servant,
    Dan

  • i++; /* increment i */

    a = b; /* save the value of b */

    /* this function calculates theta. */
    float theta(char **p, int d, float *(*fn)(int))
    {
    ...
    }

    1. The code should be written so that it is clear what it does from the code itself. Descriptive identifiers, well-focused classes and single-purpose functions all help. Careful use of white space (e.g. dividing code into "paragraphs") helps. If it isn't clear what the code does, rework it until it is clear.
    2. The code should be well-commented to explain why it does what it does. Explain how it fits into the overall scheme (and make sure you've explained that scheme).

    One way of doing this is to have a comment block introduce each class and each function. If these comments are not in a standardized format, at least make them consistant. If you're using a non-obvious algorithm, this is where you should describe it, in full. If it is spectacularly non-obvious, provide a reference to a separate doc. And if your project has created design documents prior to coding, provide references back to those docs.

    Obviously, the way code is "chunked" in item (1) has a lot to do with how it gets documented in item (2), and vice-versa; I put them in that order because it made it easier to explain, though in practice much of (2) is done before (1). But the two have to be taken as a whole and ultimately completed as a whole.

    I don't know how many times I've seen comment-as-you-go code where the comments disagreed with the code, and it wasn't clear just what a function was trying to accomplish. But if I understand the goals of a piece of code, and reasonable care has been taken in naming and organizing it, in-line comments just get in the way.

    -Ed
  • Sometimes you can use tools that help write docs based on specially formatted comments, but for most comments, all you want are:
    Paragraphs,

    written with complete sentences,
    using vanilla formatting.
    It is not widely recognized, but maintainability arguments apply to comments as well as code. When the code changes, the comments have to change too, and they should be easy to modify. That means no fancy boxes or other bizarre formatting. I don't care if your editor can handle automatic double column star boxes, not everybody's can, and to be portable (yes, comments have to be portable), you should use the absolute minimum formatting. For example:
    /* This is a block comment. It describes the block of code below. Notice that it uses no special formatting, and when I change the comment, I can hit the "reflow" button in the editor and it'll get reformatted like any other block of text. */
    Use inline comments sparingly. Write complete, descriptive sentences at the block level. It's also good to put blank lines before and after comment blocks.
  • There was a similar discussion here on /. not so long ago, and one post from it stuck in my mind as being perhaps the most worthy +5 post I'd read for a *long* time.

    Basically someone had been going through code and found an entire subroutine commented out with the rider "This doesn't work". The original poster went on to say (s)he'd initially missed the point and thought the commenter was dumb, until the penny dropped - this would be a massive time saver if someone else thought of the same routine.

    I have to admit, I'm not sure if this commenting practice would have occured to me - until I read this I'd always deleted broken code. It's definately something to bear in mind next to you waste a few hours working on a flawed algorithm.

  • In any development effort involving more than 1 person, comments are not enough.

    You should seriously consider :
    • coding standards outlining naming conventions, indentation, common usage, commenting requirements etc.
    • design and code reviews of all non-trivial work products
    • documentation standards (see the book review on agile modelling) - you should document the stuff that isn't obvious, and keep the documents up to date
    • automated unit tests which allow any changes to the code to be tested (yes, I stole that one from the eXtreme Programming guys).


    The problem with comments is that they explain what the code does, but all too often the "why" - the structure of the program - is not obvious by looking at the comments - it's like trying to work out a streetmap by looking at the names in the phonebook.

    I took over a large project from a major consulting firm; much of the code was immaculately commented, but the overall structure of the design was almost impossible to fathom; the documentation was out of date and incomplete, and everybody had a slightly different view of how things worked. Whenever we fixed a bug or made a trivial change, we'd hold our breath just in case the trivial change had unforeseen consequences somewhere else in the system. A simple class diagram and database schema would have been more useful than most of the comments. Unit tests would have saved us literally hundreds of hours of pain...

    Code Complete, a book by Steve McConnell is a great read on this subject; I also recommend "Agile Development" by Cockburn.
  • by slim ( 1652 )
    I write server code that will be run by another part of the organisation, on machines that I don't have access to. As a result it's useful to be able to turn on extremely detailed tracing so that the guys running the service can send us traces of sessions that didn't behave right.

    I find that the trace calls in the code are often as good as comments, in that someone browsing the code could use the traces to work out what's going on.

    e.g.
    for(lc=0;bytes_left>0;lc++)
    {
    trace("In main parsing loop, chunk %d, %d bytes remaining to process",lc,bytes_left);
    }

    ... tells us the purpose of the loop, and the purpose of two variables. Clearly putting a real /* comment */ next to the trace line would be redundant.

    I think even if I weren't tracing, I would place comments in pretty much the same places.Of course this isn't all the commenting I do -- there are certainly comments required above and beyond these, such as detailed descriptions of what a function should do above the declaration.
  • WHY not WHAT (Score:2, Insightful)

    by mikehunt ( 225807 )
    Certainly the most important comments are those that say WHY something
    is being done rather than WHAT is being done.

    If the code is written clearly, in sensible size functions and with
    meaninful variable and function names it is easy to see what is happening.
    It's the WHY that often escapes even the original author some
    years down the line.
  • by Rogerborg ( 306625 ) on Monday May 20, 2002 @06:33AM (#3549127) Homepage
    • All modern compilers that I know of can handle symbol names of at least 256 characters, not the old 31 character limit.
    • The most widely understood naming convention is the English language.
    • If you feel that you have to comment the purpose of a method, function or variable when you declare/define it, why isn't it necessary to comment every use of it as well?
    • The time spend typing or reading characters of code is insignificant compared to the time spent comprehending it.
    • Whenever you write code that requires any interpretation at all, you cost yourself developer time, and that's a precious resource.
    • If you comment something that the language supports, you're not using the language.
    • People who slate you for using over-verbose naming are really saying "You shouldn't need long names to understand my code." That's a solipsistic ego trip, as the target audience isn't or your peers or anyone in a code review or with white box knowledge of the code or system. It's the poor contractor shmuck five, ten or fifteen years down the line who has to come to your code stone cold on to fix a critical bug with a deadline breathing down his neck and a hankering to get the hell out of the office and have some semblance of a life. Write for the benefit of that guy, because one day you'll probably become him.
    • Every time you write a comment, you introduce a potential headache for the maintainers. Ask yourself when the last time you updated a comment in production was, even when it contradicted the code.

    Here's the rules I use:

    • A function/method name is too long when it doesn't fit on a typical screen. 80 characters is about my limit.
    • If I find myself thinking that I'd better comment the purpose of a variable, I incorporate the comment in the variable name. As a side effect, that also tends to give a good feel for how important a variable is.
    • Yes, we all know that "i" is a counter, but what is it counting? It costs me perhaps five seconds to use a variable that describes what is being counted. Then it costs a reader an extra tenth of a second to read it, but that saves a quarter of a second to translate to what it actually means. Let people read your code, don't keep making them stutter and recap.
    • Describing the function and purpose of "input" and "output" parameters in a function description comment is a hell of a long winded way of typing "const WhatTheParameterIsActuallyUsedFor". You only have to type it once; that's what copy and paste is for. Don't comment expected values, assert(them).
    • Completely self commenting code is an unrealistic ideal. But get as close to that ideal as possible, and don't be afraid to change comments when you change the code during maintenance. If you're sure what the code deos, you should have no problems doing that. If you're not sure what the code does, then find out.
  • by Bob9113 ( 14996 ) on Monday May 20, 2002 @07:36AM (#3549258) Homepage
    In any situation where I see the need for code commentary, I try first to find a way to make the code clearer. If the source code is sufficiently clear, comments are unnecessary. This also avoids the risk that the comments will diverge from the code - making claims that were once true, but no longer reflect the code's actual logic.

    This is poorly commented code (despite the fact that the comment is clear and accurate):

    aClassName = aTask.getUiInitializerClassName();
    // empty or null uiInitializerClassName means this task is not
    // defined for use in this interface. Skip it.
    if( aClassName != null && ! aClassName.equals( "" ) ) {
    ... do something ...
    }


    This is well commented code (despite the fact that there are no comments at all):

    initializerName = aTask.getUiInitializerClassName();
    boolean isNotNull = initializerName != null;
    boolean isNotEmpty = ! initializerName.equals( "" );
    boolean definedForThisUi = isNotNull && isNotEmpty;
    if( definedForThisUi ) {
    ... do something ...
    }

    Of course, this doesn't work in all situations, but I find that I can improve the clarity and accuracy of seventy to eighty percent of my commentary this way.
    • You are a moron (Score:3, Interesting)

      by RelliK ( 4466 )
      1. Your "improved" code is much less readable than the original. Whoever has to maintain it will need more time to comprehend it.

      2. You introduced a bug on line 3 (null pointer dereferencing).

      Yes, I have personally seen code like it and I wanted to shoot the fucking idiot who wrote it.
  • Golden Rule (Score:3, Insightful)

    by Salamander ( 33735 ) <jeff AT pl DOT atyp DOT us> on Monday May 20, 2002 @09:02AM (#3549648) Homepage Journal

    The most important thing wrt to commenting code is to put yourself in the reader's shoes. What would that reader need to know that's not obvious from the code? One useful exercise is to pretend that you're leaving your job and you're doing a brain-dump for the (reasonably bright) person who will inherit your code. Your goal is to anticipate every question they ask or suggestion they make, in the form of a comment. If they're likely to ask what something does or how it works, add a comment. If you add code to fix a specific bug then add a comment; obviously you didn't recognize the need for that code at first, or else there wouldn't have been a bug, so the next person probably won't either unless you comment it. If they're likely to say "this would be better if xxx" but you already tried xxx, put in a comment that says "we already tried xxx but it didn't work because..." IMO that last is the single most useful kind of comment because it saves someone from going down a blind alley. BTW, the same "role-playing" approach works really well for specs too.

    Another important skill is knowing when not to comment something. If it's blazingly obvious what something does and how/why it does it, don't comment it. If there are too many comments, the person reading the code will often decide that reading the comments is a waste of their time and they'll just start ignoring them. Then they'll miss the one comment that really does matter. If you must be verbose in your commenting, at least use some sort of visually obvious marker for really important "you'll break it if you ignore this" kinds of comments, to distinguish them from the less important stuff.

    Lastly, don't be afraid to spice up your comments. Be totally candid about stuff - yours or someone else's - that you think is brain-dead. Make wisecracks and in-jokes, within the bounds of good taste and brevity. People are more likely to read your comments if they can occasionally get a chuckle out of them. They're more likely to enjoy working on your code, and speak well of it/you when asked. These are all good things - for you, for them, for your employer or client. Coding can be dreary enough without robotic comments.

  • My list (Score:4, Interesting)

    by edp ( 171151 ) on Monday May 20, 2002 @11:15AM (#3550764) Homepage

    One purpose of comments is to explain the code to another engineer (including oneself in the future). Another purpose is to demonstrate the code works, whether an informal argument that the code does what it should or a mathematical proof. These two purposes have different needs.

    For the former case, standard writing rules apply. Decide who the audience is. I often figure the audience is an engineer who knows the type of programming at hand, but doesn't know what is done by this particular code, and may or may not be familiar with the product, depending on circumstances. Knowing the audience tells you what assumptions to make and what has to be explained, either by prose or by giving directions to reference material.

    Write complete, grammatically correct sentences. This goes a long way to making comments comprehensible. Sometimes a little phrase won't be understood because the reader can't fill in the unwritten parts, or because there's ambiguity in the wording. It is okay to use short phrases when describing objects being defined or declared (e.g., "number of links to this object" or "dollars owed this customer), but keep the context in mind. Introduce the compound object with sentences where appropriate.

    "Dollars owed this customer" reminds me -- use units. Don't write "Money owed this customer" or "time since last update." Specify seconds or milliseconds, not time. Document how the object models whatever it is modeling. That may be a physical thing like time or a conceptual thing. E.g., if a pointer connects one object to another, document the relationship that represents. If a "debt" class contains a pointer to a "person," don't document it as "person associated with this class." Document the relationship -- this particular pointer may represent the debtor, the creditor, the escrow agent, or somebody else.

    Give context. I have seen thousands of modules that just leap into code with no explanation of what they are. Even if the comments say what a function does, a reader might not really understand it until they know what it is used for. Document where the code fits into the bigger scheme and what it is used for. Give the reader context so the purpose of the function makes sense. Even if a complete mathematical description of a function is given, so that the reader can precisely predict its behavior in every situation, it might not make sense to the human mind until they have a mental image or model of it.

    For the second purpose, demonstrating the code works, explain how the code implements an algorithm. It's not enough to explain what the steps are doing; you need to show how the total result comes out of the algorithm, unless it is something simple or familiar. E.g., a formal description of the long division taught in elementary school would generally be incomprehensible. "Find the largest digit d such that d times q is less than r[i]. Subtract d*q from r[i] to get r[i+1]. Append d to output..." Nobody seeing that for the first time would understand what it is doing, even if all the steps were clear. Even if you explained each step and explained the result, it won't be clear to some readers how the steps produce the result, so explain that.

    Document alternatives that weren't chosen, and the reasons why. If you were tempted to implement algorithm X but found you had to do Y because some error might occur, record that information. Otherwise, somebody working on the code next year might see your longer code for Y and change it to X without realizing the problem.

    This isn't intended to be a complete list, just what occurred to me at the moment.

  • by goodviking ( 71533 ) on Monday May 20, 2002 @11:20AM (#3550810) Journal
    Some variation of the methods described in "Literate Programming" [stanford.edu] by Donald Knuth [stanford.edu] are a good place to start. In summary, Knuth says that you should be able to extract from the same source both machine instructions, and a human parsable document, with unusually high importance placed on the later. Whether or not you want to imbed LaTeX [latex-project.org] into your document is up to you (I never have bothered), but on the whole find something that will make your code and algorithms understandable to another programmer who's never met you (because that's probably who will be either grading or maintaining your code at some point).
  • by slamb ( 119285 ) on Monday May 20, 2002 @02:05PM (#3552164) Homepage

    Take a look at these files [uiowa.edu]. This project is basically an example of what not to do. It's faggotted up like a twelve-year-old schoolgir's notebook, to borrow a phrase from The Onion. In particular,

    • The huge block comments have these banners that are at column 1, in complete defiance of the indentation. Consequently, the indentation is not at all consistent across the code. It makes it difficult to visually see what level you are at. It makes using a folding text editor impossible.
    • there are lots of comments along the lines of "// slamb was here, 4-26-02". These are things much more appropriate for a version control system (cvs annotate). They clutter up the code unnecessarily.
    • the comments that are there explain nothing. For example,
      // This is the main method that Java invokes at start-up

      That should be obvious from the "public static void main (String argv[])".

    • They are not in the proper form for Javadoc, Doxygen, or any other documentation generator. If you go to the trouble of putting comments at the beginning of methods in structured way, you should do so in a way that can be used to generate easily browsable documentation. See Writing Documentation Comments [sun.com] at Sun.
    • The grammar is inconsistent and awkward. That same document gives hints on making useful documentation with grammar that does not distract.
    • The code is not self-documenting. If you adhere to a consistent coding standard, like Sun's Code Conventions [sun.com], you will know what a lot of stuff is without resorting to comments at all.
  • by vanyel ( 28049 ) on Monday May 20, 2002 @02:49PM (#3552537) Journal
    Unfortunately, this is rarely practical, but I find the most useful comments are written when I'm going back through code I wrote over a week ago. The reasons for doing things are no longer on the surface, and thus if there's something I look at and have to dig for understanding, then it needs better explanation.

For God's sake, stop researching for a while and begin to think!

Working...