Tdd, Kata, Dojo (and polemics)
Thus last month I did some TDD workshops. I prepared thus workshops aggregating all the information I saw, I heard, I experiment, ... and here is the result. This is a subjective point of view shared and discuss with some teams, friends, coworker, ...
What is TDD? What is not TDD?
Two rules, three steps :
- Red (meaning failure in xUnit): you cannot write more test code than needed for the tests to fail.
- Green: you cannot write more production code than needed to make the tests pass.
What is refactoring?
Refactoring is the art of modifying code to improve its design without changing its behavior. A refactoring is made of a set of smaller refactorings. When refactoring, one has to ask the following questions:
- Can I remove code smells? (dead code, duplicated code, switch cases, etc.) See: http://www.codinghorror.com/blog/2006/05/code-smells.html
- Can I implement technical design patterns? (pipeline example in FizzBuzz kata)
- Can I implement domain-specific design patterns? A non-developer domain expert must be able to understand it.
Refactoring is a continuous activity that is fully integrated to the development process proposed by TDD.
What are Katas, Dojos?
Historically speaking, katas come from martial arts. Purpose was:
Train, practice, fail, learn...
- Practice gestures, postures... in given situations, in order to get a relaxed but deep training that will allow instictive reflexes in real-world situations.
- Share fundamentals principles.
As a musician who does scales or a martial art practitioner who get trained, we as programmers do katas. There are many katas: http://codingdojo.org/ section Kata catalog (video statement and solution).
A Coding Dojo is a meeting where a bunch of coders get together to work on a programming challenge. They are there have fun and to engage in deliberate practices in order to improve their skills.
TDD myths and polemics
Here are some of the remarks we often hear around TDD and some response bits:
- A verified application
- A virtuous circle
- « Today's productivity is yesterday's quality».[i]
- Design from the client point of view.
- Less debugging
- Written documentation
- Test are written
- No time to NOT do TDD
This is a real problem and there are real solutions. Many teams have already met and overcome this. Many works (some good, others less) were written on this matter. Some workarounds are validated. Here are some good practices:
• A code running in production for 6 months is considered stable. So the idea is not to refactor all the existing code and get full test coverage on it.
• TDD will be introduced when adding a new feature. It will then be mandatory to write tests and refactor.
• For a bug fix, the very first step will be to write a unit test that highlights the bug.
• One should focus on a specific code change instead of trying to modify all at once using a legacy backlog for instance.
• In order to make existing code safe, write a unit test and check it comes out "red" when removing or commenting out the code being tested.
• Start by writing acceptance test to secure the global behavior.[iii]
Moreover, one mustn't be naive. There are problems when fixing bugs or adding features on legacy code that you can't encounter when developing "from scratch". We may get rid of these by using code isolation techniques in order to make it testable and thus refactorable. "Working effectively with legacy code" illustrates this.
The real problem to be addressed here is more "legacy team" than "legacy code". Teams that still write untested code, mainly because the feedback value still isn't anchored in their minds.
In the end, it all relies on you, the team members, the code surgeons: No one will prevent you from and no one will force you to do it. This is your choice and YES YOU CAN.
Dependencies are handled by unit tests frameworks. "Mocks", "fakes" or "stubs", which are test patterns, can be used to isolate code that must be unit-tested.
A point of interest is the impact of tests on code design. "Dependency injection" or "factory" patterns required by "mocks" and "fakes" bring low coupling on production code, preventing the spaghetti effect.
Finally what is the added value of test driven development comparing to unit test after coding?
Previously, you may have noticed some advantages of TDD over 'After Test Code’. Here are three outstanding:
a. Independence of the test relative to the code[iv]
A test written before production code doesn't check what the code does but what the code should do: by construction, it is not possible to put the obtained result in the expected result.
b. No dead code, no surplus, less bug... less time lost
Incremental construction of the product driven by the unit test involves the creation of code just to meet operational requirements: there will be no surplus or dead code and that means less bug!
c. Intrinsic quality
Refactoring is fully integrated to the development process described by TDD - red, green, refactor - As a true professional, as software craftmanship our goal is to maximize the development return on investment. Building daily quality is the only guarantee of future productivity.
Tdd, how to start?
Implementation is tricky and can become frustrating. We often hear "TDD applied to our daily work... I tried : it's just impossible." Practical implementation should not be made directly on the actual daily work: there is a learning curve. The best solution: every day for 30 minutes chrono do a Kata. Repeat until mastering, then pick another Kata. Repeat until feeling comfortable enough to switch to project code. [v]
So, « modify and pray? Or test and modify? » [vi]
• « Test-driven development », by exemple – Kent Beck
• « Working Effectively with Legacy Code » – Michael C. Feathers
• « Clean code » – Robert C. Martin
… There are many others books on the topic.
[i] Jean-baptiste Dusseaut, Arpinum, « Le professionnel », blog arpinum, http://www.arpinum.fr/2011/07/19/le-professionnel/
[ii] Colin Garriga, Yaal, www.yaal.fr
[iii] Emmanuel Chenu, Thales Avionics, « Agilité et logiciel critiques », Agile Tour Bordeaux 2010 -http://vimeo.com/19994114
[iv] Gilles Mantel, « Automatisation des tests, Le mythe du ROI », Mix-It 2012 - http://www.youtube.com/watch?v=hf__zcdihwI
[v] Peter Provost, Kata – the only way to learn TDD, http://www.peterprovost.org/blog/2012/05/02/kata-the-only-way-to-learn-tdd
[vi] Michael C. Feathers, « Working Effectively with Legacy Code »