Tuesday, March 13, 2007

TDD and Agile

Leon Bambrick (aka secretGeek) wrote a post about a possible conflict between TDD and agile, claiming TDD may be YAGNI code:
"Test-Driven Development (TDD), on the other, states unequivocally that it's worth writing extra code, lots and lots of extra code, up to five times as much code you'd write otherwise. The reasons for this are: it may stop bugs from escaping your desk -- and it may help out when you need to alter the design later."

Phil Haack countered by writing:
"Well you don't know in which specific ways your client will change his/her mind, which is why YAGNI is applied there. But you *do* know somewhere down the line, you're code will have a bug or have to change, but you don't know in which way it will have to change up front."

Do I?
Suppose 10% of my code may have to change in future, either because of requirements change or due to bugs, isn't writing tests for the remaining 90% YAGNI?
Maybe I should start writing tests for a code section only after I need to change it, as Phil later writes:

"Lastly, part of TDD is also how you react to a bug. Say you find a bug in method X. First, write a unit test that exposes the bug. In other words, write a test that fails because of the bug, but should succeed if the bug doesn't exist. Now fix the bug. Make sure the test passes. And rejoice that you now have an automated regression test for that bug. It'll never get introduced (in that way) again."

I think TDD is best practice when you are writing a framework or an API, I'm not so sure it's the best approach when you are writing a custom application.


Haacked said...

Writing tests as you find bugs is probably a great way to get started. Call it TDD-lite. :)

Another benefit of TDD is it's a satisfying approach to development. Write a test. Fail. Write the code. Pass. You create a string of small victories, rather than: Code Code Code. Test Test Test. Debug Debug Debug. ;)

As for your point about knowing that only 10% of your project will change. Are you sure?

Research show that that on average 60% of a project's lifetime is spent in the maintenance phase. In fact, as soon as you lay code down, it's now legacy.

Consider this thought experiment. You revisit some code written 3 months ago. You have to change one feature deep in the bowels of the code (maybe replacing some code with a mini rules engine. whatever).

You make the change. What confidence do you have you didn't break anything else? At this point, wouldn't you rather have a suite of automated regression tests to give you some confidence (note, I didn't say complete confidence) in your change?

According to Code Complete, there's up to a 50% defect rate when fixing a bug.

In systems I've worked on, introducing a bug when changing something was costly to the business. I was glad to have the unit tests to help keep introduced defects to a minimum.

Adi said...

I meant that even if 60% of the project's lifetime will be spent modifying code (nice fact to know, btw), only 10% of the project's CODE may actually be modified.

I agree with you TDD saves time when you modify legacy code, but is this saving worth the time spent to write those tests at an earlier stage?

It's all a question of which is more expansive in the overall lifespan of the project - writing tests in advance or spending more time when you need to modify code.

I guess you have to examine the project when you start it, and estimate the changes it may go through it's life and how much code may be changed, as well as the level of reliability required, and decide on the % of TDD code coverage you need.

Sean Chambers said...

I agree with your last paragraph adi, I think it is really a case by case basis.

Recently I made a fairly quick project that I cranked out in a couple of hours. It was a simple web form with minimal logic for a couple hundred people to submit the next week.

At first glance I knew that delving into tests was too great of task giving the deadline. Low and behold, once the project was done, it WILL be used again with more logic and more complexity. This would be a good point to add tdd to the scenario as the first time around there was a couple of minor bugs.

I believe that there is a threshold that is crossed that denotes unit tests or not. Where that threshold is, I think is determined by a number of things such as deadline, complexity etc...

There is definately scenarios where tdd is not necessary and those scenarios where it is needed.