I’ve am spending a lot of time lately programming Haskell outside of work. My goal for learning Haskell is to fully embrace all that functional programming has to offer in it’s purest form. As I am doing this, I am working to set aside my object oriented, imperative brain and learn a whole new way of thinking about solving problems.
As part of the discarding of old habits, I’ve find myself struggling to determine where Test Driven Development (TDD) fits into my new workflow as well as questioning everything I know about TDD. When I program in Ruby, I start every new feature with a test because I crave the security of knowing that I haven’t fat fingered something in the code. When I program in Java, I tend to write the code I wish to see in the world and lean on the compiler/type system to do some of the “testing” for me before I feel the need to write a test. With Haskell, I am still working to figure out how long I can go without writing a test. Partly because I’m still learning and partly because I want to experiment with a new flow. I’m finding that I can go quite far because of the amazing type system and type inference, aka Type Driven Development.
The other day I stumbled across a video from Michael Feathers titled “Testing Patience” in which he begins to pick apart the reasons we test code. For the beginning of this talk, he makes some connections to Test Driven Development and the desire for quality, among other things. And then at 11:06 into the talk, he drops this bomb:
Quality Comes From Deliberate Thought
A light went off in my head when I heard this. I had made one connection about why Haskell has allowed me to seemingly go further without writing tests first. In Ruby, I didn’t have a static type system to push me to think so I used the tests as a way to force that thinking. In Java, I have a type system but it isn’t the greatest, and some will even say that it gets in the way, but it was better than nothing. In Haskell, the clean syntax and the very strong type system really force me to think about what I’m doing and I can forego leaning on the tests to make me think. Yes at some point I will need tests for logic heavy functions but I find I can now go longer before I reach for that first test while still gaining the security of correctness by leveraging the type system. As Yaron Minsky once said, “Make illegal state unrepresentable”.
Am I on to something? Am I just crazy? Only time will tell. Regardless, I have a deeper understanding of how important deliberate thought is when writing code and that a type system is another tool to help me with deliberate thought. How are the ways that you exercise deliberate thought when writing code?