Beyond Basic TDD
The session started with a question from Waseem Taj, who observed that the traditional red, green, refactor TDD cycle did not always result in well designed solutions. Jeffrey Fredrick noted that Kent Beck recently revoked his original thoughts on emergent design, with the realisation that you have to actually be a good designer for this to work. The general consensus was that you must keep refactoring until the design is right, and have the courage to say "we need to do more." -- Refactor Mercilessly
The discussion turned to Kent Beck’s Four rules of simple code, and particularly to the need to express intent in your tests. Ask yourself "what does this class need to do," not "what methods should it have." When pairing, one person should be ensuring that the design is moving in the right direction. Good pairing partners are relentless in their insistence on refactoring.
The conversation turned focus on going beyond TDD, with Gojko Adzic posing the question "What do we need to teach TDD practitioners to get them to the next level?" He mentioned several concepts:
- Evolutionary Design
- Exposing Design Presumptions
- Hexagonal Architecture
- Naming Conventions
The initial reaction was that it was extremely difficult to teach advanced TDD techniques, and that experiencing the benefits first hand by paring with a practitioner was the only realistic way. Steve Freeman said that "until you experience the whole rigorous TDD, refactor cycle, you will never get it."
Several ideas for learning were proposed.
- Have a sandpit codebase, or a pet project (one that actually goes live somewhere so that it isn't entirely fictional) People can often translate from an example to their real code.
- Code dojos
- Have the right to experiment and to throw away those experiments.
- Apprenticeships and staff swaps
- Give an exercise to express a difficult intent in a test (e.g. write a test for the generation of a random number)
- Try writing your test's assertion first
- Show how to do things badly (refuctoring)
- Try reversing refactorings to see if they still apply.
- Write code in the test and refactor it out ("TDD as you meant it").
- Stop after 15 minutes and Ask yourself: "Can I check in now?". If the answer is no, ask: "Will I be able to check in after another 15 minutes?" If the answer is still no, then ask why, and consider reverting.
- Get the whole team to work on the same area of code simultaneously. This encourages frequent check-ins to avoid merge conflicts (only those who commit often will 'win').
- Do a visualisation of bugs raised and fixed, allowing developers to get experience-points for cleaner code.
- Try measuring a different code metric each week. Changing the metric frequently discourages 'gaming' the system. This encourages conversation about aspects of the code.