For those who know me, have worked with me, or have suffered through one of my rants, it will come as no surprise that I despise the notion of TDD. However, I’ve hesitated to blog about this subject until now for two reasons. Firstly, it’s an unpopular opinion, and I didn’t want my opinion to reflect poorly upon the company I run. Secondly, I have no desire to write provocative blog posts, and argue with random strangers who disagree. However, after watching DHH’s 2014 RailsConf keynote, I feel obligated (and inspired) to echo his sentiment.
I love Rails. I’m a Rails zealot. I’ve been building web software for over 15 years, have coded in tons of languages and frameworks, and I’ve never found a tool more comfortable and productive as Rails. But Rails is more than just a tool, right? Rails represents a collection of beliefs on how web software should be architected, built, configured, organized, and tested. Rails was a loud voice screaming “MVC” and “RESTful design” when those were unfamiliar to most. It screamed “Convention over configuration” to embarrass the Java folks. It took all the best ingredients of how web software should be built and maintained, and wove them together through years of aggressive evolution.
Rails will likely fade away some day, but I can guarantee you that whatever takes its place will borrow many of those some ingredients and core tenets. Your investment in its principles and ecosystem will never be a waste of time.
However, there’s always been one core tenet that I’ve resisted. One that didn’t feel right. Test Driven Development.
In the late 80s, G.E. Smith was the musical director for Saturday Night Live. I actually didn’t know his name until now when I googled him. He played the guitar and led the band. There was always a close-up of him before and after commercial breaks. I hated the guy. HATED. His facial expressions and weird hair drove me nuts. But I loved SNL. And so I spent years trying to convince myself that I liked him, so that I could enjoy the rest of the show. I lied to myself over and over and over again, hoping I’d start to believe it.
It never worked. I was ecstatic to see him leave in the 90s.
TDD was another G.E Smith moment. I tried to love it, because I felt like I couldn’t be a Rails guy without preaching it.
When I first learned about TDD, it seemed right. I struggled to adhere to it, but parroted it’s importance to the development teams I ran. I touted its benefits to executive management. I devoured books and blog posts on the it. However, the more I learned, and the more I tried it, the more I disliked it.
But I desperately wanted to like it. I remained hopeful that I was misunderstood or that I just wasn’t doing it right. I eventually took a TDD course by a highly respected group. I contained my skepticism for the first day, and did everything by the book. I even learned some new things. But by the second day, the instructor was demonstrating a test for a list view. First the test barked because there was no route. Then he created the route. Then it barked because there was no controller, so he created the controller. Then there was no index method, so he created that. Then there was no view, so he created that.
I interrupted and asked, “You’re just using this as a simple example, right? In reality, you wouldn’t intentionally skip all of those steps for things so obvious, right?”
He looked at me like I was crazy, and said, “No, I do this for everything.”
“Really? Isn’t that a waste of time?”
“No, you’d be surprised at how often you miss minor details, and the tests help you.”
That was it. I was done. I’d officially joined the Fuck TDD team.
Let me be clear, I believe in testing. I’ve inherited and built too many apps to not understand the value of regression testing. If you don’t write tests, you’re a fool. But I write tests after I write code, not before.
I’m an expert developer; I know what I’m doing and don’t need to be led down a path by failing tests. I can get in the zone and crank out massive chunks of functionality in a short amount of time. Stopping to write or run tests is a distraction and stunts my progress. In a world where developers preach Vim because your fingers don’t leave the home row, how does running tests every ten minutes not impact your efficiency?
I hate starting with red. Red is bad. It makes me feel like I’ve done something wrong. There’s something so backward about intentionally starting with failure. That makes me feel like we’re creating a generation of passive developers. Do you walk out of the house naked everyday, and wait for your neighbor to scream at you to put clothes on. Or do you act like a big boy and dress yourself? (don’t answer that!)
I code because I like to create things. I build products with Rails. My job isn’t to write the world’s most comprehensive test coverage, it’s to solve problems with software. Tests are used to ensure that my software is stable, but they are a bi-product, not the product. It kills me when I see people using ugly design patterns in their code to make their tests run faster. That’s prioritizing tests over product. There’s no business value there. If you care more about the internals of the codebase, than the product itself, you’re doing it wrong.