Tuesday, July 10, 2012

TDD, do you speak?

Tdd, Kata, Dojo (and polemics)



Context


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.
  • Refactor.
TDD is not a way of testing or writing unit tests. It is a process, a way of coding . TDD is made of small cycles, small steps, small victories, ranging from test code to production code. As every other development process, TDD doesn't question the presence of integration testing and manual testing.

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.“Tons of useless tests!!!” A verified intrinsic quality 
  • A verified application
The all test harness allows to have a verifiable application: on a distributed project, with 20 parallel developments. If  the "red, green, refactor" process is followed up then, any time, everyone can stop coding and within a minute (time to get back to last green state), a version can be delivered (almost … :p)
  • A virtuous circle
Did you ever get into that situation? You are reading bad code, you want to refactor it, and ... no, finally: "it stinks, but it works … if I modify my code I’ll never be sure that the behavior will be maintained...". The fear of regression. What does remove that fear? The tests which are a security harness. We refactor to obtain a quality code and we can refactor because we have tests that remove the fear of refactoring. "Red, green, refactor" must become our mantra.

b.« All thus tests! It’s a waste of time ! » I do not have time not to do TDD
 

  • « Today's productivity is yesterday's quality».[i]
Quality code is possible if code is refactored, code can be refactored if it is tested, non-tested code cannot be refactored: it's a technical debt that will have to be paid (either by writing tests later or by having a high impact on productivity when we add new features).

  • Design from the client point of view.
The activity of typing code is not time-consuming. Thinking about the code we want write and designing it is. Writing a test is the formalization of a code design process : a definition of your API [ii]. Writing a test and the associated production code do not take more time than thinking/designing the code and write it. Moreover, it is designing the code from the point of view of the one which will use it and this may be one of the greatest virtue of TDD.

  • Less debugging
The biggest advantage of TDD is the time that is not used to debug the software. Tests will influence your design. The code will be naturally modular, functions will be smaller and unit tested. Bug fixing will be fast. The point here is that we are making a fruitful short term investment.

  • Written documentation
Tested code is documented code, so there is no time needed to write a technical document explaining how to use the code.

  • Test are written
The unit tests are finally done! The (in)famous "write unit tests" post-it is included in the development process.

  • No time to NOT do TDD
Finally, when you balance the job done (unit tests are written), the alive code documentation, the fruitful work and the formal design, to "we've got no time to do TDD", I reply "I don't have time NOT to do TDD". :-)

c.« With legacy code, you can't do TDD» With legacy team, you can’t 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.

d.« Network, file system... With all these external dependencies, I cannot test!» Mock, Fake, … your dependencies

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]





Literature


•    « 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.

Thanks!!

Alexandre, Colin, Denis, Jean-baptiste, Samuel 

 

Sources


[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 »

No comments:

Post a Comment