Fri, Nov. 16th, 2007, 02:18 pm

BDD: Bug Driven Development



"We'll need to create this domain object," she said, "and a database table."



"I don't want to do that," I said. "I'd rather fix the stuff that's broken."



She looked puzzled. "What do you mean? We haven't written any code yet."



"Well, we know that if you go to the URL, you should see the form. But when I go there I get a 404 error."



"Well, yes. We haven't written any code yet."



"So, it's broken. It doesn't work yet. We should fix that."



So we wired up the container and knocked out a controller. We restarted the server and refreshed the URL. Spring told us we had left out a couple of things. We fixed those.



Negin tapped something into the template and refreshed the URL again. "We have a page. It says HELLOOOOO! across the top. Now what?"



"Well, we got rid of the 404 error. But the page doesn't look right."



"Of course not. We haven't written the form yet."



"We should fix that."



We wrote the form. It didn't look right, so we added the styling. Our business analyst peered over our shoulders at what we were doing. "Looks like you're doing well. Why doesn't the drop-down have my data in?"



Negin said, "You're right. We should fix that. This is fun!"



"It is," I said. "Don't you just love that we get paid for this?" Today, Negin and I paired on a brand new piece of work."We'll need to create this domain object," she said, "and a database table.""I don't want to do that," I said. "I'd rather fix the stuff that's broken."She looked puzzled. "What do you mean? We haven't written any code yet.""Well, we know that if you go to the URL, you should see the form. But when I go there I get a 404 error.""Well, yes. We haven't written any code yet.""So, it's broken. It doesn't work yet. We should fix that."So we wired up the container and knocked out a controller. We restarted the server and refreshed the URL. Spring told us we had left out a couple of things. We fixed those.Negin tapped something into the template and refreshed the URL again. "We have a page. It says HELLOOOOO! across the top. Now what?""Well, we got rid of the 404 error. But the page doesn't look right.""Of course not. We haven't written the form yet.""We should fix that."We wrote the form. It didn't look right, so we added the styling. Our business analyst peered over our shoulders at what we were doing. "Looks like you're doing well. Why doesn't the drop-down have my data in?"Negin said, "You're right. We should fix that. This is fun!""It is," I said. "Don't you just love that we getfor this?" Fri, Nov. 16th, 2007 03:19 pm (UTC)

(Anonymous): Fixing things Great! Now after you finish "fixing" your Web application, "fix" it so that it works on cell phones, is Section 508 compliant, supports multiple browsers well, and can authenticate users versus an Active Directory or LDAP store, too. Fri, Nov. 16th, 2007 05:18 pm (UTC)

johnhutch And, in the process, rewrite your app 10x. Funny to think about, terrible in practice. And, in the process, rewrite your app 10x. Funny to think about, terrible in practice. Fri, Nov. 16th, 2007 05:57 pm (UTC)

sirenian It's working for us so far (but it's an internal site, so we don't have to support mobile phones etc. - bit easier!) Fri, Nov. 16th, 2007 07:39 pm (UTC)

anthonybailey I hear the concern, but I don't agree with the numbers (10x is very pessimistic) or the conclusion (I find one can usefully grow these kinds of apps incrementally.)



Hearing the concern: yes, if you're pretty sure you know where you're going, then a cost-effective way to meet many of the requirements at once probably involves doing the app in the context of some existing framework. (Or perhaps some more abstract large architectural pattern than a concrete framework; but the same reasoning applies, and the issues are more concrete with a real framework.)



And if you start simple, outside of the (then unnecessary) framework, then often the refactor step that ports into the framework is a relatively large one that is hard to provoke through always trying to do the simplest thing that could work for any one new feature. So I frequently find there is quite a tension between B/TDD's incrementality, and sensible/timely framework reuse. It's a challenge!



However, I venture that it's worth trying to learn to walk this path nonetheless. "I think I know where I want to get to. Which next step moves me in the right direction, safely, whilst giving me the chances to spot early if I'm wrong about where the real destination actually is?" I continue to get gradually better at it, and I find that it's easier the more modular the target frameworks are.



The step-by-step route one ends up taking is indeed a bit longer than the distance to the final destination as the crow flies. But, I don't find the longer distance is ten times as far - more like twice. And given how often I'm a bit wrong about where I need to end up when I first start, I'd probably pay a similar rewriting cost if I assumed my big design destination up front. ("Plan to throw one away...") And, even the one slightly scary nearly-a-rewrite refactor that bites the bullet and squeezes the stand-alone app into the chosen framework is well-covered by tests, so it's a still a safe step, and it's taken at a time when I've lots more confidence about my choice than I'd have had at the start. Meanwhile throughout the journey I have working software, a good idea how far I have yet to go, and all the surprises along the way are relatively small. I hear the concern, but I don't agree with the numbers (10x is very pessimistic) or the conclusion (I find one can usefully grow these kinds of apps incrementally.)Hearing the concern: yes, if you're pretty sure you know where you're going, then a cost-effective way to meet many of the requirements at once probably involves doing the app in the context of some existing framework. (Or perhaps some more abstract large architectural pattern than a concrete framework; but the same reasoning applies, and the issues are more concrete with a real framework.)And if you start simple, outside of the (then unnecessary) framework, then often the refactor step that ports into the framework is a relatively large one that is hard to provoke through always trying to do the simplest thing that could work for any one new feature. So I frequently find there is quite a tension between B/TDD's incrementality, and sensible/timely framework reuse. It's a challenge!However, I venture that it's worth trying to learn to walk this path nonetheless. "I think I know where I want to get to. Which next step moves me in the right direction, safely, whilst giving me the chances to spot early if I'm wrong about where the real destination actually is?" I continue to get gradually better at it, and I find that it's easier the more modular the target frameworks are.The step-by-step route one ends up taking is indeed a bit longer than the distance to the final destination as the crow flies. But, I don't find the longer distance is ten times as far - more like twice. And given how often I'm a bit wrong about where I need to end up when I first start, I'd probably pay a similar rewriting cost if I assumed my big design destination up front. ("Plan to throw one away...") And, even the one slightly scary nearly-a-rewrite refactor that bites the bullet and squeezes the stand-alone app into the chosen framework is well-covered by tests, so it's a still a safe step, and it's taken at a time when I've lots more confidence about my choice than I'd have had at the start. Meanwhile throughout the journey I have working software, a good idea how far I have yet to go, and all the surprises along the way are relatively small. Fri, Nov. 16th, 2007 03:55 pm (UTC)

icklemichael You lot have the craziest office banter! You lot have the craziest office banter! Fri, Nov. 16th, 2007 07:42 pm (UTC)

goawaystupidai Also known as: Test Driven Development. TDD doesn't always have to be done by first creating an automated test first. Sometimes just human driven testing is enough to find something to fix.



With a strong bent on refactoring I've had great success using this method. Also known as: Test Driven Development. TDD doesn't always have to be done by first creating an automated test first. Sometimes just human driven testing is enough to find something to fix.With a strong bent on refactoring I've had great success using this method. Fri, Nov. 16th, 2007 09:40 pm (UTC)

(Anonymous) That is wrong.

TDD always includes time-taking tests, autotesting and stuff.



I think its a wrong design choice



the best ways to code are:

knowledge & experience

oop as a THINKING pattern (not the C++ model)

Fri, Nov. 16th, 2007 10:14 pm (UTC)

goawaystupidai Originally TDD was used to refer to development that was focused on verification of requirements before development of requirement satisfiers. At some point a bunch of extreme programming fanatics who never bothered to read beyond the catch phrase started claiming automation of TDD was the only way TDD could be done. TDD is well grounded in the scientific method. And if you recall the scientific method: A proper science expirement that is not automated is still a proper science expirement. Although there can be great costs savings in automating things that's all it is: Cost savings. If the the cost/benefit evaluation for automation doesn't work out then don't automate.



In the domain of TDD: If the cost of developing an automated test is too high the correct response is to perform a manual test. In which case the process is *the exact same* as what you retold above. Verify the system fails to satisfying the requirement. (The test phase) Then resolve the failure. (The development phase). Whether these should be automated or not is a seperate issue.



For instance, compilers are just an automation of part of the development phase. Originally computer languages were used as a formal communication method using pen and paper. The translation to machine code was done by hand. Sure glad that was automated... ;-)

Originally TDD was used to refer to development that was focused on verification of requirements before development of requirement satisfiers. At some point a bunch of extreme programming fanatics who never bothered to read beyond the catch phrase started claiming automation of TDD was the only way TDD could be done. TDD is well grounded in the scientific method. And if you recall the scientific method: A proper science expirement that is not automated is still a proper science expirement. Although there can be great costs savings in automating things that's all it is: Cost savings. If the the cost/benefit evaluation for automation doesn't work out then don't automate.In the domain of TDD: If the cost of developing an automated test is too high the correct response is to perform a manual test. In which case the process is *the exact same* as what you retold above. Verify the system fails to satisfying the requirement. (The test phase) Then resolve the failure. (The development phase). Whether these should be automated or not is a seperate issue.For instance, compilers are just an automation of part of the development phase. Originally computer languages were used as a formal communication method using pen and paper. The translation to machine code was done by hand. Sure glad that was automated... ;-) Sat, Nov. 17th, 2007 03:10 am (UTC)

(Anonymous): TDD symbol Time for namespaces.



Master::TDD == "Top down design"



Punk::TDD == "Test Driven Development" Sat, Nov. 17th, 2007 12:52 am (UTC)

(Anonymous) Excellent post!!!

(Szczepan) Sat, Nov. 17th, 2007 04:55 pm (UTC)

(Anonymous) It is interesting, we talk about patterns, best practices etc and at the end of the day it all comes down to doing simple stupid things during day work. boring but we get paid for it. Mon, Nov. 19th, 2007 09:53 am (UTC)

sirenian Yeah, there's lots of different ways to make best practices happen, and they're usually small but stupid. I find them lots of fun, too - not completely bored yet! Tue, Dec. 18th, 2007 11:41 pm (UTC)

peterbell I saw this posting when it first came out (and loved it), but I only just caught the comments. This is exactly the way I'm moving towards developing and I find it is incredibly effective. Anthony is right that if you're doing "just another project" you may already have a framework in place that takes care of some of the steps. We typically just describe the business objects, screens and controller actions declaratively and use that to gen the first cut of the code, but when you get down to writing some custom code, creating the simplest thing that could pass the test just rocks.



A couple of years back I would never have considered such an approach. Too much of a waste of time (as mentioned by our anonymous user above). However, I now find that this approach really helps you to stay in the zone and motivated as you have "lots of little wins" along the way.



A friend was getting in trouble trying to figure out how to abstract a validation library that could be composed into their business objects for handling common classes of validations. I immediately suggested just writing the first few business rules by hand. Think up the test, pass the test, and then if appropriate, refactor to a common library. That way you can focus on what you really need rather than trying to come up with the uber-validation library which (at least for me) ends up with analysis paralysis.



I know this is really obvious, but it still feels good when you really start to internalize the process. I'm certainly finding that it makes programming a lot more fun and rewarding and a lot less anxiety provoking. And to the commenter who thinks this is all about doing stupid simple things, if you can't enjoy small triumphs when your tests turn green, perhaps programming isn't your path? I just love getting paid to do this stuff - even after over fifteen years.

