Teaching Test-Driven Development

My friend Ola Berg asked for my view on a blog post by Justin Searls: The Failures of “Intro to TDD”.

I’ve been teaching TDD for a couple of years (started out with Emily Bache back in 2009 if I recall correctly) and I’ve tried to follow up on each class I’ve run to see what works and doesn’t. I’ve surveyed the 150+ participants before, 6 and 12 months after attending my TDD class.

The below notes are a short response to the article, based on what I’ve found and learned from my own teaching.

On Teaching

Hitting real production code

There’s lots of Code Katas (a kata is an exercise that should be repeated in order to train your ability to perform a series of punches, moves and kicks in karate) that allow you to practice the TDD “moves”. The idea is that after doing so in a safe environment, you should easily be able to use the “moves” - now in your muscle memory - in the heat of the (code) “fight”.
That idea certainly works for a lot of people, especially those that get test-infected after first exposure. But in my experience, this doesn’t come easily to the majority. So I include more realistic code situations and actual code and frameworks. With most classes, where participants aren’t fresh out of school, I make sure I include katas/exercises which contain real production code and realistic scenarios. The two last sessions of a course usually consists of exercises where we use their own production code. (And occasionally, they get back to me and we use a pool of hours where they present a tricky case where they’ve got stuck not knowing how to test or move ahead. Of course we turn that in to a coding dojo session, instead of just handing over a solution.)

No short intensive trainings

One of the “challenges” put forth in the article is “how do you condense years of industry best practice [into one person’s brain]”? Well, for the majority of people, one exposure of a new idea and concept and practice doesn’t make them an expert. An expert can extract useful pieces, pros and cons and apply them in new situations, instantly. To even become rudimentary proficient with something that’s new to your brain, you need repetitive exposure and practice.
That means any short high-intensive exposure of a lot of new concepts, ideas, practices, rules of thumbs, … will likely project a similar retention of that exposed information: short.retention, it’s forgotten all too soon to be a worthwhile investment. I only teach TDD over several weeks where the students are given weekly assignments to take bake into “the real world” and then bring back their findings so we can explore them and I can provide (hopefully) guidance and help bring “order” to conflicting from new thoughts and “old learnings”.

Learning iteratively, incrementally

Taking it step by step, with sufficient time for reflection and repetition in your own pace helps strengthening some learners, primarily those that don’t “get it” right away.

When I revisit students for a new training session, I sometimes get struck by how they present a much clearer view on things than what they had when I left them. The amount of processing and reflection, and re-exposure, needed for this kind of deep learning to happen - well it doesn’t happen over night (when dealing with lots of new concepts, tricks, … - not for most people).

Disclaimer

People learn in different ways. Do what you can to accommodate the people in class, don’t go looking for the one true way. I don’t believe in that. A good teacher will see what’s needed and support the group in their moving forward.

Hmm, come to think of it again, I do think there’s one way of learning which is almost universal: you learn better by doing it yourself (ie practicing using your own brain and hands, as opposed to hours of watching and listening only).

On TDD

Short comments:

  • I find Justin rambling a little and not making clear points about Classical TDD vs Mockist approach. I think it’s important to point out that there are different approaches of doing “test first” and not one solution fits every bill. The way your system is constructed (or will be) should impact on how you approach solving the problem. Not every problem is a nail - try to see when to use a screw driver etc.
  • I usually refer to Tomek Kaczanowski’s definition of ‘Workers and Managers’, pretty much like ‘Collaboration and Logical’ used by Justin in the article.
  • The idea of reductionism is an observation I’ve seen quite a few people make, typically from people coming from computational science side of things

The last D

Is TDD about Design or Development? Will ‘reductionism’ lead to great design? Will reductionism ever lead to implementing a Visitor pattern?

I absolutely agree that some design aspects benefit from having code being test-driven, but not every aspect of a system’s design will improve simply because we wrote the tests first. I don’t buy that selling point. I’m not sure Justin is trying to make that point fully, but I’m not part of the front claiming that TDD will improve the overall design of your system. It should make it testable, and that’s probably going to help making it modularized/segmented properly, but there’s no guarantee you’ll get that simply because your TDDing all production code.

Last Words

I understand - and agree with - most of what Justin’s after (I think), but I believe his points are mostly valid when teaching TDD as a short course. I’m sure he’ll inspect and adapt - I can assure you that I have! :-)

This work by Fredrik Wendt is licensed under CC by-sa.