September 26, 2007The less tests, the betterBrian Doll posted a few interesting questions as a comment on my "Continuous tax" entry, which I'll try to address in turn: Oddly enough, some people see the act of writing tests as "continuous tax" in that it's something else you have to write that does not go toward the "bottom line" of the features you're implementing.Actually, I don't see writing tests as part of this continuous tax that I was describing earlier. While I agree that you usually write less tests in a statically typed language than a dynamically typed one, I think the difference in lines of code or number of tests is not significant enough to meaningfully impact the engineering cycle. The continuous tax is triggered by the loss in explicitness that dynamic code usually suffers from. While it looks innocuous, the loss of typing actually has dire consequences on the maintainability and readability of your code by not giving you any hint on what type an object passed to a method really is and, worse, by making it impossible to apply even the simplest automatic refactorings such as renaming public functions (see this post for more details). I'm interested to get your thoughts, as an author of a testing tool, on how you see the overall reliability of testing in dynamic and strongly typed languages.As shocking as it may seem from the creator of a testing framework and the author of a book on testing, I actually always try to write as few tests as possible. The secret is to find the smallest subset of tests possible for a given functionality. The way I see it, dynamically typed languages usually make me write the following tests:
In the past couple of days, a few people have chimed in with their private experiences of the continuous tax, among which Mark Derricutt and Eric Burke. What's interesting about a continuous tax is that you keep paying it all the time to the point that you might even forget about it. From that respect, I wouldn't be surprised to see that developers who work with dynamic languages on a daily basis encounter the problems described by Eric and Mark regularly, but they just don't notice any more: it's just part of their routine. Java (and other statically typed languages) developers simply don't ever pay this particular tax, so having to face these problems feels like a step backward in productivity (obviously, Java programmers pay different continuous taxes in other areas, but let's save this topic for another day). In a comment on Eric's post, Weiqi wrote: In that regard, the static typing works just like unit tests - it prevents you from breaking your code.... which summarizes this issue pretty well: static typing gives you tests for free, and who would turn down free tests? Comments
I think good arguments for static typing like context-sensitive help, readability and reliability can all be considered a wash for various reasons. But Refactoring is just unbeatable - a huge win for static typed languages. Context-sensitive in dynamic lang IDEs could just provide a larger set to choose from and as methods are chosen object contexts get even narrower. Readability and Reliability have so many more factors than just "typing" and cannot really be used as arguments. Proper designs, documentation and unit-tests play much bigger roles in this. It really, really comes down to Refactoring - the biggest productive gain in programming within the last decade - (i believe we can thank IntelliJ for this). I rely on it constantly - across large project sets on a daily basis. I cannot imagine how the dynamic folks can maintain medium to large projects without refactoring over several iterations over several years of requirement additions and changes. Posted by: Sony Mathew at September 27, 2007 11:31 AM"I cannot imagine how the dynamic folks can maintain medium to large projects without refactoring over several iterations over several years of requirement additions and changes." Perhaps they compose larger software from smaller independent parts, rather than composing large software from large interdependent parts. Posted by: Ricky Clarkson at September 27, 2007 12:53 PMRicky, most folks design the best separation of concerns they can see at the time and into the near future. Refactoring plagues every application as it ages - no one is immune - great books have been written on the topic. As Jeff Foxworhty would put it - "You maybe a consultant" if...(place what u said here)..or "You maybe inexperienced (aka consultant)" if.. place what u said here) hahaha...just kiddin ... Posted by: Sony Mathew at September 27, 2007 01:36 PMI think Ricky stroke a rather important nerve when saying "[dynamic folks] compose larger software from smaller independent parts, rather than composing large software from large interdependent parts" and that is that "usually" when working with dynamic languages your code is not that complicated and tends to be smaller. There are plenty of examples in Java land alone where you can see larger & complex components for even larger and complex projects. Refactoring is king, and although in dynamic languages you don't need it as much I very much like to apply some refactoring techniques when doing Groovy code. That would be a task for tool developers, at least on the Groovy side both IDEA and Eclipse teams are working hard on cooking basic refactoring capabilities. Remember that Java tools have many years of advantage over the dynamic languages, it may take at least a year for them to catch up (but I'd like to be wrong and hope it takes less time :-)) Peace. Posted by: Andres Almiray at September 27, 2007 03:07 PM"Tests to verify type consistency." Could you give a concrete example to help me understand what this means? How would this not be covered by a unit and/or functional test? Posted by: Paul Barry at September 27, 2007 03:20 PMWhy would you want to write tests to verify type consistency when you already check types in tests? def test_url_for Post a comment
|