Sunday, 5 June 2016

Learning to TDD is like learning to drive a car

Its true (well sort of)

When I was learning to drive I was pre-occupied with where to put the gear stick, where it actually was, when to use the clutch and so on and so forth and being flustered all the time.

But, quite quickly, with continued practice and with growing familiarity and confidence with a car, I could think about where I wanted to go instead of every detail of what I needed to do, to get there, and now I drive like Lewis Hamilton.

Before  I could start to TDD fairly well (In my .NET C# world) and be able to decide what works for me (for example choosing when to use classic and mockist TDD) I had to become comfortable with some pretty basic things including a good refactoring tool - ReSharper, a good test runner and Unit testing framework like NUnit and a good test isolation (mocking) library, like Moq (all of these tools have their proponents and detractors)  but this is what I use for the majority of the TDD I do at the moment, this could change, but the principles won't.

I've been TDD'ing - or at least - trying hard to TDD over the last couple of years and it has been a grind. 

I've read TDD by example by Kent Beck about 10 times (but never to the end) and watched plenty of videos and read blogs and - in spite of being told that practice makes perfect - have not practiced anywhere near enough - I just dont't have the opportunities in work time alone to do this (but that's another story - and that is in spite of being a TDD first organisation).

Taking my lack of practice by the horns after reading Sandro Mancuso's book -  The Software Craftsman this coupled with Roy Oshrove's string calculator kata (and many others like it),  Growing Object Oriented Software Guided by Tests  (GOOS) by Steve Freeman and Nat Pryce, Mocks aren't stubs  by Fowler and Sandi Metz's take on what and what not to test 
a few things changed and things have, seemingly, finally clicked.
(Edit: 31/10/17  I  am reviewin Sandi Metz's TDD eBook, 99 Bottles of OOP and the first impressions are really good) 



TDD Bigger than the sum of its parts

Using the tools I mentioned above will get you writing unit test's pretty quickly but not TDD'ing.  Using the tools and TDD'ing will get you TDD'ing but most likely in haphazard manner.

Firstly, TDD'ing at all requires confidence in the tools, mentioned above, and not worrying or having to think about how to use  them - its not that they are extremely complicated to use, but things can get bloody confusing.  Using Moq, we can create Mock objects which are Stubs or we can use Mock objects to verify behavior with them.   Of course, this can be done without Moq, but it is great at creating Mocks and Stubs, quickly.

(Edit 31/10/17 Perhaps I have overstated having to use these tools.  Using things like Resharper are really helpful, but not the be all and end all of course.  And of course you could write your own Stubs and Mocks -  I guess my point was that these things help speed up development somewhat and getting up to speed with them takes a while but also at my company I had to learn these at the same time. In retrospect  perhaps it would be better to not use these types of tools AT ALL - when starting out - to really get some of the fundamentals down, especially the really intricate part of slowing down TDD and being very thorough and organised and applying a regimented approach, which  I have come to appreciate more as time has gone on - and  having read more about - even just recently.)


(Edit 31/10/17 However,... ) Using a good refactoring tool really helps speed up things too, but - again - to use one fairly well there is a bit of a big curve learning useful shortcuts but then once this has been done learning when to pull objects into existence or when they should be Mocked or Stubbed needs to be learnt.  

So we have the tools and we need to learn how to use them and when to use them and why to use them.  This is a lot to learn and then apply. However, when all of this starts to fall into place, wonderful things start to happen and the productive ebb and flow of  TDD, which before, was likely staccato comes to the fore. 

With this, and something  I forgot to mention, pairing with people when TDD'ing loses the scare factor, worrying about how to use the tools is a bit of a disadvantage and can disrupt the flow of pairing, it can make you feel pretty stupid if someone is already pretty comfortable, even if you are far from it.  Nobody likes to appear like a novice - not knowing how to find a gear or the accelerator if comparing to driving.    
(Edit:  31/10/17  Perhaps knowing the tools would be less of a worry if you knew the intent and understood the implications of what people you are pairing with are doing, a tool can be picked up and put down but understanding is a much slower gained but sought after quality) 

So the upshot of having the requisites in place is that shaping applications, driving the design by pulling in collaborators (either by Mocking or Stubbing them) with a quick refactoring short cut can all be done under the TDD cycle with confidence and very nearly without a thought as to how you are using the tools to get to your end goal - you are just using them as a means to an end. This is a really fulfilling feeling. 

Summary

I am writing about my experiences with TDD as I've struggled with it, and watching people around me get it and not having that same Eureka moment (or moments) has added to my anxiety, stress and worry that I would never be able to TDD effectively.  But I think I am just about there, I always like TDD'ing,  I now think that I can do it pretty well.  And on this note if other people are having trouble with it, stick with it, practice a bit more - read a bit more too, make sure you are reading the right things,  some things may likely only make sense when you have some of the other fundamentals boxed off.

Happy TDD'ing.