Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • by btilly (5037) on 2009.03.08 17:40 (#67737) Journal

    My previous comments on method length were not advocating longer methods. I generally prefer shorter methods myself. But there is a tension between what I believe works and the research I have seen.

    The problem with the studies cited in Code Complete is that they were generally done in procedural languages before people adopted object oriented approaches. Does research on what works in procedural programming still apply to code written in object oriented or functional styles? Good question.

    I don't have an answer to that. But other research has consistently found that function complexity matters more than function length. A long function that happens to include a big hunk of text is generally not a maintenance problem, while a shorter function which is a twisty maze of conditions and loops often is. One measure of complexity is cyclomatic complexity which is basically the number of decision points plus 1. That is 1 for entering the function, and 1 for every if, while, ||, etc. The rule of thumb is that a complexity not apply to object-oriented code.

    However I know of no research on this topic. This is just my personal impression.

    On your main article, I'm religious about very little in the programming world. However to my eyes the value of testing is not that you write better code, it is that you have an easier time maintaining that code once written. In fact I would maintain that good tests and poor code is more maintainable than no tests and decent code, because with the former you know when it breaks, and you are more able to address the deficiencies in the code.

    Furthermore on the research that you cited, I am hardly surprised that when you take people and ask them to develop code in an unfamiliar way, the effort of thinking about the new skill and new discipline will make them perform worse. While programming we have to juggle a lot of things in our head, and having to hold something unfamiliar in your head while you do that will reduce your ability to manage complexity. Therefore more of your mental balls are likely to drop, and that shows up as worse quality.

    However I would then go further and argue that what holds true for beginners holds true, albeit to a lesser degree, for experienced programmers as well. Switching from coding to writing tests and back interrupts the flow of your thoughts. Given how valuable mental flow is, this disruption has a cost. The disruption is lessened because of the relationship between the test and the code.

    For "boring" code this overhead is a non-issue. For "interesting" code, any overhead is going to limit your abilities - it is much better in my experience to write the code in a single go, then go back and write tests to validate what you did. In general reading code you wrote half an hour ago takes far less concentration than writing that code. Plus in the process of writing tests you get the opportunity to revisit your logic and catch bugs. While I am a fan of not commenting code unnecessarily, if it was "interesting" to write, it may well be worthwhile to insert some sort of explanatory comments as you write your tests.

    The on case where I absolutely am in favor of test driven development is in bug fixing. You have code. Someone found a clear bug in it. You write a test that shows the bug in operation. You fix the bug. You see that the bug went away. There are three reasons for this. The first is that writing the test for the bug often narrows down where the bug is likely to be. The second is that it can be useful to look at what is happening in a bug in detail, in which case the test you just wrote that creates the bug situation is very useful. And the third reason is that if you do things in the reverse order there is a real possibility that you make a change that doesn't fix the bug, then write a passing test that would have passed anyways, and don't fix the bug that you thought you fixed. (This is not hypothetical. One ticket assigned to me for a company I am contracting or is about a bug that a previous programmer "fixed" in exactly this way. Since the bug is only triggered on a race condition they couldn't test the fix either way, and the only way they know it didn't work is that they are still getting errors in their log.)