At some point, the conversation focused on testing in Clojure. Recently, Rich Hickey said something at the Strange Loop conference comparing Test-Driven Development to driving a car around banging into the guard rails –I actually don’t know the exact words, I wasn’t there and didn’t see any video. This is not the first time Rich says something like this, and years ago Donald Knuth said something similar.
It should be very clear to readers of this blog that I use Test-Driven Development in pretty much all code I write; but I have absolutely no problem with what Rich or Don said.
I have a limited view of the development world
Over the past decade I’ve been writing systems for banks, real-time billing systems, massive scale multimedia distribution and all sort of application domains. I am convinced that this kind of work benefits a lot from having executable specifications written up front, and to me the best way to write executable specifications is with tests. I was never paid to write a programming language or any hardcore systems-level code, though
Just as some hardcore systems programmers tend to say things that are completely bogus in my world (in the old days this would be something like “real men write it in C”), I am aware of the fact that I shouldn’t try to sell the tools I find useful in my tiny little corner of the development world to everyone.
I have friends who solve hard problems without even running a test for months, and it works for them. Could their feedback cycle be made shorter by introducing TDD cycles? I suspect yes, but I have no experience in the kind of work they do; so instead of bringing in my pitchfork and torch I would rather seat down with them over beers and compare notes.
TDD is neither requirement, nor guarantee
One thing I’ve learned early in my career was to always read the source code of whatever tool I am using. Since I started playing around with Clojure I tried to get myself familiar with the implementation of the language, and even hacked around a bit whenever there was some need or opportunity.
As someone who spent the past few years reading the Clojure code base every now and then, I don’t have a lot to complain about the readability of the code.
Interestingly, the same mindset of always read the source code made me read many frameworks, libraries and tools in multiple languages. There is little correlation between readable code and usage of TDD by the author; even though usage of TDD by the developers makes me much more confident in changing code and sending a patch, even if the code is a mess.
There is no real guarantee that a TDD code base will provide you with better or more readable code; what TDD helps with in this case is making it much easier to know if a change to some piece of –good or bad– code is correct or if you broke something by mistake.
So what’s the deal, should we do TDD in Clojure or not? I surely believe that most people would benefit from TDD in Clojure, Scala and other Functional languages; it works for me, has been working for a decade. I am more than happy to show you how so, and see if I can help you in applying the techniques I use in your reality (in fact, I just proposed a Better Functional Design in Clojure through TDD talk for the next Berlin Clojure meetup, you should come along!), but there’s no way I would say that this is the only way to have a good and reliable code base.
That said, just as I see a lot of die-hard TDD people complaining about Rich and Don’s words, I see a lot of cool kids using them to ditch good practices in software development as something irrelevant in Clojure. Well, the last time I saw this happening was a couple of years ago, when the Ruby on Rails cool kids decided that Ruby was so awesome that they could just drop whatever practices they thought were not cool. The consequences of this mindset are not, well, awesome; so be careful here.