During the last half of 2014, I feel like I really got myself in a rut. I wasn't learning anything new. I didn't take as much pride in my craft. There's no doubt about it, I stopped challenging myself and got complacent. I'm sure I could find several good excuses for why things reached that point, but the responsibility is mine alone. (Unfortunately, the blog host doesn't support embedded YouTube videos, so I have to old school link it) Reminds me of this great clip from Rocky 6. The point is, it's time to up my game.
I've been reading a lot about test driven development (TDD) lately. For a long time, my thoughts on the subject of testing were that it's BORING, not value added, and difficult. One of the really intriguing advantages that I read about was how well executed TDD enables and enhances code refactoring. It really is a great feeling to know that you can change your code and not worry that you're missing some edge case that you'll have to go back and fix again. That is a huge positive in my book. But it always seemed like a huge amount of work.
But Testing is Hard
Most of the projects I work on are very small scale, a few hundred lines of code, maybe. And most of that is UI work. I have done a few projects with a few thousand lines of code. In those cases, I think some automated testing could have been beneficial. But for the most part, it really felt like testing was something for people that didn't write solid enough code and something for projects with teams of developers. To burden myself with that level of process and overhead just seemed like a good way to slow me down and grind down my motivation and desire to develop even further. I've got solutions to get out the door. Still, I couldn't help but feel that I was missing out on something very significant.
Every developer on the planet has their own way of writing code, their own style choices that make them unique. So, while there are some best practices that are widely recognized, we still start with a blank canvas. The code we write has to meet the needs of the customers and has to be reliable. Usually beyond that, all bets are off. In larger teams there are a lot of opportunities for peer review and more experienced folks to guide one along. On open source projects, there's a huge potential audience. I would certainly feel pressured to put out a higher quality product if I knew more people were viewing it and raising their eyebrows at my complacency or convoluted attempts at logic.
What a Fool I've Been
I'm pretty sure it's worse to know better and still do something sloppily, than to do it out of ignorance. It's a pretty horrible thing to have to admit. If one doesn't handle a simple project properly, how can they possibly be expected to handle a project that's an order or two more complex? But still, I'm lazy (which isn't always a bad thing for a developer) and loathe to put a lot of time into improving code that maybe me and one other developer will ever see. And besides, how can I have any confidence that I'm actually getting at a better end product anyway? There are code metrics tools, but they don't really guide you, they validate.
And here is where the testing component comes back into play. Because designing the solution to be testable from the ground up enforces the loose coupling and modularity we desire. If I write a solution to fetch data from a database and display it on a web page via a web service and client scripting, I'm liable to combine functions in ways that make testing extremely difficult. And because of how I inadvertently coupled things, it becomes a huge task to refactor. Then, I don't want to refactor the solution because I don't want to manually retest things to make sure I didn't break anything important. Which leaves me with a blob of code that works, is logical and easy to follow, but is not satisfying, is not truly elegant.
I'm not dogmatic about very many technology choices or design decisions. Blindly following a process, approach, or methodology simply because it yielded results for some other project or in a different environment is, in my view, a recipe for disaster. One must first understand the reason an approach has been successful. What are the major characteristics and do those factors make sense in the present context? TDD is not the silver bullet. It is still possible to produce a horrific system within that framework, but I think it will help me get to the next level and I'm excited about the journey!