TDD is Kanban for Code
The other night Cynthia and I were having drinks in the Tower Bar of the Hotel Hafen in Hamburg (highly recommend for the view if not the service) with Henning Wolf and Arne Roock of it-agile when I casually mentioned that test-driven development was kanban for code. Arne teaches kanban but the connection wasn’t obvious to him, so I sketched my idea (see napkin above). He seemed to understand (he kept nodding, anyway), but I thought it prudent to follow up with a post to make sure I’d thought the whole thing through. Arne, this one’s for you.
The goal of kanban is to increase the value of a production process. Kanban increases the feedback in production by limiting the amount of work in progress at any one time. Without the “safety” of inventory, troublesome process steps and connections between steps have nowhere to hide. With better feedback, the steps can be optimized (or eliminated) and their connections improved. The result is higher throughput and lower latency and variance.
Kanban works by only producing on the basis of demonstrated need. While one finished product is being assembled, upstream steps are producing the parts for the next finished product, timed to arrive just as they are about to be used. When a kanban system is humming, it produces a steady stream of finished products with a short gap between the receipt of an order and its fulfillment. When it isn’t humming, the source of the dischord is likely to be clear.
Test-driven development (TDD) is an alternative programming workflow where features are divided into a series of automated tests. The tests are chosen so that satisfying the spirit of all the tests implies that the feature as a whole works correctly. The cycle goes like this:
- Write the next test (while several tests may be outlined, only one is written at a time)
- In pessimistic languages, add enough stubs so the test compiles. It should fail when run.
- Refactor, if necessary, to prepare for the implementation.
- Change the logic of the system so the test passes.
- Refactor to eliminate duplication and other excess complexity
Repeat until no more of the tests implied by the feature would fail. Then the feature is complete.
If TDD is kanban for code:
- What is the product?
- What is the kanban card?
- What are the production steps?
- How does demand flow backward and products flow forward?
- What are the feedback loops?
The product of software development is two-fold:
- The behavior of the system
- The options for extending and modifying that behavior in the future
As difficult as it can be to precisely specify and validate the behavior of the system, it is even harder to measure a system’s option value. Finding the right balance between these two goals is one of the big challenges of development, especially as different phases of the business cycle require different proportions. I’ll describe in a moment how TDD addresses this balance, both in theory and in practice.
The tests are the kanban cards in this system. Each one is a request for a change of behavior. “Please change the system so if the customer is a smoker the premium is 12% higher”. This will require changes to the logic of the system. It may also require changes to the structure of the system so the change to the logic is easier to make correctly and efficiently.
The post-success refactoring commonly emphasized in descriptions of TDD isn’t explicitly called for by the tests. It is work done for future benefit. If the future happens to be the next test and implementing it is easy because of cleanup done after the last test was satisfied, then the payoff is immediate. From the kanban perspective, though, post-success refactoring is over-production, the worst of the seven wastes of the Toyota Production System. Still, most TDDers, myself included, clean up after a test is passing as a matter of habit.
The behavior and options are the product, the test is the kanban card, so that makes the production steps the changes to the logic and the changes to the structure of the system. In TDD, these changes are not begun until a test is failing. The changes flow forward into the product, as demonstrated by the passing test, and the lack of collateral damage is demonstrated when all previous tests also pass.
Feedback loops fuel kanban. In TDD, the programmer gets feedback in seconds about whether the logic implied by the test is the logic he writes. He also gets feedback about whether the design supports the logic changes based on how hard or easy those changes are to get right.
This isn’t the whole story of development. Post-success refactoring doesn’t fit into this picture but is a common practice. Is this just because of our still-evolving understanding of TDD, or is it more like the preventative maintenance needed to keep kanban systems running smoothly? Should some or all of it be deferred until immediately before it is needed? What about other valuable software development activities like automation, tool building, and exploration?
We could also pull back and look at development at a larger scale and see the features as kanban cards, each one “pulling” a collection of tests into the system, triggering coding. From even further back, a process like Customer Development can be seen as “pulling” demand for features.
In any case, TDD is kanban for code:
- Product = behavior and options
- Kanban card = test
- Production step = coding and refactoring
- Feedback = effort and test results
Arne, how does that work for you?