11 ms·
The Most Important Code Isn't Code
- kenneth_reitz 15y agoI couldn't agree more. Writing documentation tells me more about my own code than any level of testing ever has. Both are important of course. ;)
- humbledrone 15y agoYou mean to say that a test like the following wouldn't be better than the comment for multiplex()? unless multiplex('Tom', 4) == 'TomTomTomTom' raise TestError( 'multiplex() failed' ) end Not only does that test communicate the exact same thing as the documentation comment, it is guaranteed to be correct and not out-of-date (assuming it's run as part of a test suite), whereas the comment can easily be wrong.
- abecedarius 15y agoIt doesn't communicate the same thing. It communicates one example, leaving the reader to guess how to generalize it. Examples are good, testing is good; and specs are good too. It's currently popular to valorize the first two at the expense of the third, but I think this was an overreaction to the older dogma.
- msbarnett 15y agoIf the general behavior of multiplex isn't clear to the api-user from the example: multiplex('Tom', 4) == 'TomTomTomTom' I'd argue that's a failure of the api designer that no amount of documentation is going to make up for. Examples are good, testing is good, executable, testable documentation is doubly good, and predictable, intuitive api interfaces are invaluable; everything else is a liability that is going to go stale.
- abecedarius 15y agoCovering every case provides value that covering just one does not. Natural language communicates in a way code does not. The tradeoffs are a bigger topic than I feel like arguing about in this thread. (I agree with all you said except the last clause.)
- cema 15y agoWhat is the expected behavior of, say, multiplex('Tom', 0) or multiplex(null, 2) ?
- kragen 15y agoWell, if the function was designed by me, then the completely obvious answers are '' and a NullPointerException. Anything else is bug-prone — if the first case does something different, then nearly every caller of the function will need to check to see if the count is zero, or it will get behavior for that case that is not correct for its purposes; and if the second case does something different, then the function is choosing to provide incorrect output instead of crashing. Also, I would have called it something different. However, over the years, I've learned that many things that are obvious to me are not, in fact, true. So, what are the arguments for any other possible behavior?
- cema 15y agoBackward compatibility could be one such factor. In any case, documenting edge conditions helps in code maintenance.
- kragen 15y agoSince I'm coming from Python, JS, and C, passing a null instead of a string doesn't seem like an "edge condition"; it's the same kind of error as passing an integer or Map instead of a string. Passing 0, I suppose, is an edge condition.
- kragen 15y agoEven the Agile Manifesto itself explicitly says that its signatories value comprehensive documentation. They just value working software even more.
- bxr 15y agoI had written a really long response here, drawing on my experience as a software tester. I've deleted my post and have decided to argue my point in another fashion. Please enlighten me to the meaning foo(), here is the documentation: tests = [ #Format: [InputA, InputB, InputC, InputD, Output1, Output2] [1, 2, 3, 4, 12, -7 ], [2, 3, 4, 5, 27, -14], [3, 4, 5, 6, 48, -23], [4, 5, 6, 7, 75, -34], [5, 6, 7, 8, 108, -47], [6, 7, 8, 9, 147, -62], ] for a, b, c, d, o1, o2 in tests: failUnlessEqual((o1, o2), foo(a, b, c, d)) Can you tell me what foo() does please? Its a ridiculously simple function. I work with tests like this quite often. It doesn't confuse me though, I like to put comments in my code and even the test code, but you don't need those.
- humbledrone 15y agoNope, I am not going to bother. Your function has a terrible name, and the names of the arguments are not available to me. Had you given it a good name, and listed its arguments, I bet that the test would be quite a nice example of how to use it.
- bxr 15y agoBut my documentation runs during the hourly and never raises any red flags! That means its right, therefore better than a comment. edit: You did kind of prove my point by asking for documentation outside of the test. If this "documentation" test isn't enough to find out whats really going on in my 1-line function, what makes you think a test and the best-chosen names in the world would give you any insight to a 2-line function?
- humbledrone 15y ago> But my documentation runs during the hourly and never raises any red flags! That means its right, therefore better than a comment. Your words, not mine.
- deleted 15y ago[deleted]
- humbledrone 15y agoThe documentation example for the multiplex() function seems like massive overkill to me. The most informative part of the documentation comment is the line that starts with "Duplicate some text..." So why not just name the function duplicate_text() and be done with it? The arguments could be documented similarly, by naming them "text" and "num_duplications". I don't think I'd need an 11 line comment to tell me what this definition did: def duplicate_text( text, num_duplications ) text * num_duplications end In fact, I might prefer NO comment, because comments can become out of date and misleading, whereas the code always tells the truth.
- holman 15y agoThat was pulled from the TomDoc spec- it was designed to demonstrate TomDoc, not the code. Having an overly complicated implementation makes explaining the documentation side of things a bit more difficult. :)
- humbledrone 15y agoAh, I see, it's an example of how to, not when to. :)
- nightski 15y agoBut that is a good point you make :) Is it maybe not the documentation that matters so much but the semantics communicated through the code itself? Documentation is important, its just how its done today that bothers me. I have been reading the book "Computational Semantics with Functional Programming" and it has been quite intriguing. I would highly recommend it.
- kjmclark 15y agoBut "TomDoc is a mentality". What the heck is "TomDoc" anyway? The author says it's a mentality, but since when do mentalities come with specs? As far as I can tell, it's an example of a function spec that's so badly written that it needs a huge comment to explain it. Lousy name, lousy parameter names, no statement of what it returns, no actual return, etc. Maybe the author just needs a language that declares returns and some practice at naming variables/functions?
- waratuman 15y agoGood documentation is great, but its importance grows with the size of the project. It isn't as important in a Rails app where only a few people touch the code and the concepts already well known about the framework. The project can grow both in terms of code size and the number of people engaged. Each drives up the importance of documentation.
- JoeAltmaier 15y agoI can't express how many times I've seen code with comment block boilerplate at the start of every method. And nothing filled in. Its really more common that the other kind. So sure, we all know its great to document. The challenge is figuring out how to get it done. Given that we're all in a hurry, mean well but think we'll get back to it. It feels like you're doing something when you paste in all those blank comment blocks. But soon you don't even see them, since first off they're usually blank, and second when debugging you're looking for the code not the comments, since if it all worked like its commented then there'd be no bugs.
- nickolai 15y ago>since if it all worked like its commented then there'd be no bugs. Unless it is no longer supposed to work how it was originally written and commented. Software lives and evolves over time. All too often comments go stale. When the Big Bug Day comes, many hours will be wasted on such legacy comments.
- jacques_chester 15y agoAs I understand it, the difference here is that the documentation is actually tested automatically. I believe Python has a tool like this too. Edit: or maybe not, I can't see mention of it on tomdoc.org. However the format lends itself to that. For contrast, the D language allows inline tests.
- GFischer 15y agoAt some of the more orderly places I've worked, we put dates on comments. Also, whenever we made a change, we put a comment (at the top of the class, function, method or whatever is changed), also timestamped, with a reference to the change request ticket (or equivalent), and a summary of the change. Old comments were deleted if necessary (you could always look them up with a diff on the source control) Said ticket also had a reference to the code file :) so you had 100% traceability. The downside being of course it was all very bureaucratic, but there were legal requirements to fill and it was a sensitive, finance sector company. That setup probably wouldn't work for a fast-paced startup :)
- tlrobinson 15y agoEven better than documented code is code that's so clear it doesn't need explanation, with occasional comments explaining the complicated bits. The other case is API docs for libraries and frameworks meant for external consumption.
- nonzero 15y agoI actually comment even simple code because comments show up a different color in my editors. Comments for me are often an additional mnemonic trigger rather than necessarily a store of detailed information. It's like indenting or bolding text. It helps with "chunking" while skimming code.
- gruseom 15y agoThe trouble is that the very same visual cue makes it easy to filter out comments as background noise, so people fail to read them (or even see them) when updating the associated code. As a result, comments don't get maintained and become inaccurate over time. It takes only a small amount of such semantic decay before the comments are a net negative. Programmers take code seriously. Most don't take comments seriously, even when they believe they ought to. You might say they're bad programmers, but I don't think it's that simple. I think the attention goes straight to code for a reason.
- lurker14 15y agoFor this purpose, whitespace is a much better tool than blocks of lorem ipsum. Braces (in relevant langauges, like C and Java) are even better, because they tighten scoping and avoid unintentional variable re-use.
- rokhayakebe 15y agoAn experienced engineer told me the purpose of documenting is not to tell what the new few lines do, it is to explain something that does not look right, or something to be careful with.
- sofuture 15y agoI absolutely agree. I don't comment all that much, but comment where it's impossible to get clarity -- or comment at a higher level to explain the rationale for the code. Commenting what code does -- is either 1) pointless or 2) indicative you should rewrite your explanation-requiring code in a more straightforward fashion.
- abecedarius 15y agoWhile I mostly agree, breaking out a comment for every parameter tends to wordiness and to encourage you not to see and explain your purpose synoptically. Like, this: > Perform an n-fold frobulation. > @param n the number of times to frobulate > @param x the x-coordinate of the center of frobulation > @param y the y-coordinate of the center of frobulation > @param z the z-coordinate of the center of frobulation could be "Frobulate n times around the center (x,y,z)." (From http://stackoverflow.com/questions/499890/what-is-your-personal-approach-take-on-commenting/500268#500268 http://stackoverflow.com/questions/499890/what-is-your-perso... ) So the example would go "Return text concatenated count times." I'd try rewriting the longer example from a diff message in the OP, except it didn't fit in its own snippet! A wordy style makes writing and maintaining comments feel like a chore; feeling like a chore, it gets done less. People start finding reasons comments are bad, and taking them for the whole story.
- deleted 15y ago[deleted]
- jacques_chester 15y agoOne thing my supervising professor has prodded me to do is to begin keeping a working journal. Nothing fancy, just a plaintext file with date markings. I've heard the idea before and dismissed it, but it's surprising now how often I will go back and check that journal for why I did something. I already try to write informative git log entries, but the journal really lends itself to long form exposition.
- wglb 15y agoOk, I'll be the curmudgeon here. In recent software development efforts I have run, I have put for the rule that "All comments are bugs". Comments get separated from the code, make statements about obsolete activities, and often mislead the reader, and even sometimes the author. In place of comments, write code that is as self-explanatory as possible. I refer to Martin Fowler's "Refactoring" as a way of trying to increase my authority in the matter. However, I do back off from this extreme position and put comments on individual methods. Sometimes. What helps is using longer method/function/attribute/variable names than pg or tptacek would. I think the TomDoc example is particularly poorly chosen for the author's thesis, as, more often than not, one is likely to just do "text * num_duplications" inline, no? So why is this even a separate method? Certainly not to save lines of code. As noted in other comments to this submission, the real value of comments is the why of doing something unusual, not what. And who was it that said that the Ruby community should spend more time on documentation rather than tools for documentation? A case in point is the doc for EventMachine. This is an insanely useful tool, yet every time I look for the answer to a question about how it operates, the auto-generated documentation leaves me disappointed. If you are going to spend time on documentation, there is the place to spend it. Make your code readable in its own right.
- gruseom 15y agoI find your comment valuable and largely agree, but it spurred me to write out an objection I have to a common view (not necessarily yours). What helps is using longer method/function/attribute/variable names Sounds great, so why don't all good programmers do that? This is a deeper question than it seems. Over time, I've come to mostly prefer short names. The reason is that longer names add lexical noise to the code; they distort its structure and thus drown out other important information. The lexical is only one of several semantic channels and there are tradeoffs between them: you can't optimize clarity via verbosity. After a certain point (rather quickly, in fact) inflating the code detracts from clarity overall. It's easy to miss this because one often is making X more readable by giving it longer names or spelling its logic out in detail. The trouble is that other things than X have now become more obscure. The question is, what maximizes the clarity of the program as a whole? I'm pretty sure my code would evoke howls from the "all code must be immediately readable [to me]" brigade. I used to feel the same way, but now I don't. It leads to sacrificing deeper comprehensibility (of the entire program) for superficial readability (line-by-line). Maximizing the overall clarity of a system is closely tied to distilling its parts, and the connections between them, to their minima. Code inflation inhibits this. The demand for immediate readability comes from a belief that all code should reveal its secrets immediately. That would be great, except it's impossible. There's a fundamental complexity tradeoff at work. If you opt for verbose readability, you end up with code that is line-clear (I know this function is saving a record to a database or whatever) but system-incoherent (why the hell is it going to the database here?) Talented programmers who care about readability but have a superficial view of what that is end up producing systems with far too much code. They accrete code, which may be impeccably pseudo-readable, when what they ought to be doing is distilling it. Such code is like the old joke about the person lost in a hot air balloon who calls down and says "where am I?", but the guy they're talking to is a technical person who answers, "you're in a balloon twenty feet above the ground". Programs that are built for global intelligibility usually have much less code, but not necessarily the sort you can scroll to and immediately grok. You have to work to begin to understand the program, but once you absorb its conventions understanding proceeds much more rapidly. Latency is worse this way, but bandwidth is orders of magnitude better. The reader I feel responsible to is the one who is willing to put in this work. After all, they're going to have to do it anyway to get anywhere nontrivial.
- ajg1977 15y agoThe most recent breakthrough in my coding style has been naming methods and variables so that documentation of anything other than input expectations is largely unnecessary. In your example something like textByRepeatingText(text, times)
- pestaa 15y agoSorry but I had to think really hard to figure how the name textByRepeatingText could have been thought up. It might fits your thinking, but it certainly doesn't mine. Documentation is the common language (hopefully).
- roryokane 15y agoOther people have already said most of what I wanted to say – that self-explanatory code, and sometimes tests, is almost always better than comments. I just want to point out a good reference on this topic: the book Clean Code: A Handbook of Agile Software Craftsmanship [1], specifically Chapter 4, “Comments”. That chapter gives examples showing which comments should be turned into code and which are acceptable to leave as comments, and it explains the reasoning behind the choices. (And the rest of the book teaches you how to make your code self-explanatory and easy-to-read.) [1] http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 http://www.amazon.com/Clean-Code-Handbook-Software-Craftsman...
- ark 15y agoGreat article. However, you should be using YARD. Along with: https://github.com/lsegal/yard-spec-plugin https://github.com/lsegal/yard-spec-plugin
- sprint907 15y agothats all good for one line functions. When you start writing functions with more than 5 lines....
- 6ren 15y agoExamples are great documentation. Python's doctest automatically tests them ensuring they still work.
- stayjin 15y agoI think thar the most valuable documentation are the commit comments for the version control system you use. Especially if one uses the incremental iteration paradigm, the commit history together with the code diff IS the documentation of one's code in it's most fundamental way, that is when I changed something, why, what I was ( thinking that I was ) doing etc. In case that one has to maintain existing code, of course, the whole history is not available but still, refactoring committed similarly documents the evolution of the code in a similar way.
- asymptotic 15y agoMost discussions about commenting necessarily revolve around how to comment functions/methods/classes, when to comment, how to write code that is so intuitive that it doesn't necessarily require commenting, etc. In my opinion, these discussions miss out a key documentation requirement: describing how everything fits together. Let's assume the supposed best-case: every single method and class is commented using a language-specific documentation system (I'm thinking of EDoc for Erlang, Javadoc for Java, etc). Who cares? Congratulations: I now know how all your functions work. But what is the system architecture? How do object instances of the different classes hang together to support the functional specifications? What is the sequence of events for various successful and failed transactions? I suppose what I'm complaining about is the rationale that code commenting can necessarily substitute a solid set of functional specification and design documents. Then again, noone here made this suggestion, so maybe I'm just whining into a black hole. The only open-source project that comes to mind when I think of an astoundingly high quality of documentation is SQLite in the form of "Inside SQLite (2007)" (O'Reilly); unfortunately it's not free.
- parren 15y agoThis is also known as "literate testing", as in Python's doctest. I have collected some information on it here: http://arrenbrecht.ch/testing/ http://arrenbrecht.ch/testing/.
- martinsolivera 15y agoI think that a good code talk for itself. Explain a code sounds like to explain a joke.