Date Archives

March 2013

Test Driven Development and Positive Reinforcement

I love writing code using test driven development. But this will not be a post about how to test drive your code. There are plenty of very good articles available and, of course, the Kent Beck book. I will reference the obligatory Wikipedia definition, though.

Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.

This will not be a post about how TDD improves code quality and design. These topics have been well covered. This post is much more personal.

Let’s walk through a typical TDD session: I write a test. I watch the test fail. I implement code. I watch the test pass.

At this point, I’m engaged and excited about moving on to the next test. I know that I’m on the right path and it feels good. I repeat the cycle in short intervals, each one leaving me increasingly more satisfied with what I’ve accomplished. Ballooning test counts give me a sense of how far I’m progressing. I often get into a state of flow and can lose myself in the code.

These micro goals and feedback loops have a fascinating way of reinforcing our behavior. Video game designers have been exploiting the power of positive reinforcement for years. Gamers keep playing in order to get that next win or next reward. With TDD, each passing test is a “win” and I want to keep going. I’m doubly motivated if I implement some code and the test is still failing. This is Albert Bandura’s self-efficacy – “the measure of one’s own ability to complete tasks and reach goals” – in action.

Research on game theory helps us understand why this works:

The flow we experience when playing a great game is a prime example of how we can condition other parts of our lives. Because of this, flow has become central to game theory. Good games that are responsive to player ability and game difficulty are framed as microcosms of optimal experience. They give the player a sense that their skills and abilities are adequate for coping with the challenges presented, and are based around “a goal- directed, rule-bound action system that provides clear clues as to how well one is performing”

TDD truly is about so much more than testing. The feedback loop inherent in TDD feeds us with positive reinforcement that our minds crave. The quality and design improvements that TDD lead to are nice, as well 🙂

“Common” Sense?

I’m sitting around, waiting for my hellfire chili to finish cooking and I came across this gem written by Ron Jeffries. If you’re involved in any way with software development, this is a phenomenal read.

His second paragraph starts off with this:

Most of us were taught to write down all our requirements at the very beginning of the project. There are only three things wrong with this: “requirements,” “the very beginning,” and “all.” At the very beginning, we know less about our project than we’ll ever know again. This is the worst possible moment to be making firm decisions about what we “require.”

And he follows that up with:

Then we demand that the developers “estimate” when they’ll be done with all this stuff. They, too, know less about this product than they ever will again, and they don’t understand most of these requirements very well.

To me, this is common sense. We don’t ask students to take an exam before learning the material. That’s not practical. Yet big requirements, long term projections, and unrealistic dates show up everywhere. Of course, the folks funding software projects want to know how much they need to invest and when they’ll get something for their investment. We’re not manufacturing a car, though. There’s no blueprint when we’re developing a new product. Why isn’t this common sense in software projects?

Tonight I wanted something spicy. The chili recipe I mentioned is like a set of requirements – this is how to make a spicy dish. I’ve never made this recipe before, so I decided to experiment with the heat level. I knew from previous experience that habanero peppers are hot. Really hot. In fact, six habaneros sounded like it may melt my face off. So I added what I thought I needed, measured the heat level, then adjusted.

I’ve posted before that I believe what we really want is to minimize the cost of change. When teams struggle to change direction, the tendency is to lock in requirements and delivery dates. If a simple change in requirements leads to a huge change in design, product teams will be instructed to define everything they want before development starts. “Changing requirements will cause us to miss our deadline” we’re told. Of course, as Ron points out, these requirements are rarely correct because they are defined when we know the least about what we’re building. Projects end up taking much longer than anyone wants and deliver features that nobody wants. So the lesson is that software developers need to make it simple to accommodate change.

Naturally, Ron is much more eloquent:

And you need to know how to build software that is soft enough, malleable enough, to grow smoothly as it needs to.

Working in short iterations frees you to change direction. To incorporate feedback. To learn. To build software that people want instead of software that visionaries think people want.

This simply makes sense to me.

And by the way, the chili was fantastic. It’s a deep burn, but delicious. If I made it exactly as the recipe stated I would have likely thrown the whole pot in the garbage and cooked up a frozen pizza.