Exploration Through ExampleExample-driven development, Agile testing, context-driven testing, Agile programming, Ruby, and other things of interest to Brian Marick
|
Fri, 29 Aug 2003Christian Sepulveda writes about comments in code. Not all comments are bad. But they are generally deodorant; they cover up mistakes in the code. Each time a comment is written to explain what the code is doing, the code should be re-written to be more clean and self explanatory. That reminded me of the last time someone mentioned to me that some code needed comments. That was when that someone and I were looking at Ward Cunningham's FIT code. The code made sense to me, but it didn't to them. You could say that's just because I've seen a lot more code, but I think that's not saying enough. My experience makes me a particular kind of code reader, one who's primed to get some of the idioms and ideas Ward used. I knew how to read between the lines. Let me expand on that with a different example. Here's some C code: int fact(int n) { // caller must ensure n >= 0 int result = 1; for (int i = 2; i <= n; i++) result *= i; return result; } I think a C programmer would find that an unsurprising and unobjectionable implementation. Suppose now that I transliterate it into Lisp: (defun fact(n) ; caller must ensure (>= n 0) (let ((result 1)) (do ((i 2 (+ i 1))) ((> i n)) (setq result (* result i))) result))This code, I claim, would have a different meaning to a Lisp programmer. When reading it, questions would flood her mind. Why isn't the obvious recursive form used? Is it for efficiency? If so, why aren't the types of the variables declared? Am I looking at this because a C programmer wrote the code, someone who doesn't "get" Lisp? A Lisp programmer who cared about efficiency would likely use an optional argument to pass along intermediate results. That would look something like this: (defun fact(n (result-so-far 1)) ; caller must ensure (>= n 0) (if (<= n 1) result-so-far (fact (- n 1) (* result-so-far n))))(I left out variable declarations.) Unless my 18-year-old memories of reading Lisp do me wrong, I'd read that function like this: (defun fact(n (result-so-far 1))
"OK, looks like an accumulator argument. This is probably going to be recursive..." (if (<= n 1) result-so-far
"Uh-huh. Base case of the recursion." (fact (- n 1)
"OK. Tail-recursive. So she wants the compiler to turn the recursion into a loop. Either speed is important, or stack depth is important, or she's being gratuitously clever. Let's read on." With that as preface, let me both agree and disagree with Christian. I do believe that code with comments should often be written to be more self-explanatory. But code can only ever be self-explanatory with respect to an expected reader. Now, that in itself is kind of boringly obvious. What's obvious to you mightn't be obvious to me if we've had different experiences. And the obvious consequences aren't that exciting either: The more diverse your audience, the more likely you'll need comments. Teams will naturally converge on a particular "canonical reader", but perhaps that process could be accelerated if people were mindful of it. We could do more with the idea. The line by line analysis I gave above was inspired by the literary critic Stanley Fish. He has a style of criticism called "affective stylistics". In it, you read something (typically a poem) word by word, asking what effect each word (and punctuation mark, and line break...) will have on the canonical reader's evolving interpretation of the poem. To Fish, the meaning of the poem is that evolution. I don't buy this style of criticism, not as a total solution, but it's awfully entertaining and I have this notion that people practiced in it might notice interesting things about code. Affective stylistics is part of a whole branch of literary criticism (for all I know, horribly dated now) called "reader-response criticism". There are many different approaches under that umbrella. I've wanted for a few years to study it seriously, apply it to code, and see what happened. But, really, it seems unlikely I'll ever get the time. If there's any graduate student out there who, like me at one time, has one foot in the English department and one in the Computer Science department, maybe you'll give it a try. (Good luck with your advisor...) And maybe this is something that could fit under the auspices of Dick Gabriel's Master of Fine Arts in Software, if that ever gets established. Recommended reading:
|
|