implements Elegance {

// Elwyn Malethan's musings on software development, mountain biking and general navel–gazing...

Why TDD: Freedom to refactor

Dave and Jen work for software companies that produce exciting and clever software products. Both Dave and Jen understand design patterns. They both know about encapsulation, inheritance, composition and all that jazz. They‘re both good software developers. The only difference is that Jen has taught herself to develop test-driven. Dave thinks his time is better spent writing production code.

Dave and Jen started their current project at the same time. Dave spent some time up–front to carefully design his architecture to the requirements and implemented all the features. Dave added some unit tests, but only as an afterthought. Dave is confident that his architecture is well suited to providing a maintainable solution to the requirements specified. Dave is OK with the fact he has less than 25% test coverage.

Jen used TDD, she started off by adding some tests to represent some of the requirements and implementing production code to pass those tests. She did this iteratively and in small digestible chunks until she had satisfied all of the requirements. Jen changed the architecture of the project frequently. She refactored as she went, renaming classes and methods so that they better represented their function, moving code and responsibilities between classes to continually improve the design of the software. She did this safe in the knowledge that her tests would pick up any errors introduced. Jen builds up test coverage of over 80%.

As always happens in a software project, the requirements change. In Dave‘s case, management decided that – for political reasons – Dave needed to completely change the way his product worked. Jen‘s customer‘s priorities changed. To stay competitive, they needed to have different features. In both cases – as ever – time was short and deadlines were tight.

Both Jen and Dave found that their existing design wasn‘t really suited to the new requirements. Dave was concerned about the deadline and the time it would take to evaluate the correctness of any change he made in the design of the software. He has no timely or repeatable means of doing this. So Dave added the feature without changing the design. He knew it wasn‘t ideal and that the he would need to change the architecture at some point in the future. Given the time constraints, Dave believed he was being pragmatic.

Jen – on the other hand – had been refactoring the code extensively throughout the development of the project. Jen recognises an alternative design that would elegantly accommodate this new requirement and refactors. She runs the tests to see if she broke something. A few of them fail. So she fixes them and runs the tests again, safe in the knowledge that her tests represent the requirements.

Over the next few years a number of new features are requested by both Dave‘s and Jen‘s customer(s). Each time, Dave opts for the change that least affects the existing code-base. Each time Dave‘ project becomes more like a ball of mud. Dave becomes more and more resistant to new features. He started asking management for some “engineering time“ to refactor the code and have the time to evaluate it‘s correctness. This – he knew – would take some time.

In the same time, Jen‘s team have been doing nothing but implementing new features. The design of the software has changed frequently in that time. She doesn‘t need any “engineering time”, her tests evaluate the correctness of every feature she adds.

Dave has become scared of changing the code, he doesn‘t know what he might break.

Jen breaks the code every day. She‘ll know in seconds what she‘s broken and what she needs to do to fix it.

The design patterns link above is an affiliate link. Any and every software developer should have a well–thumbed copy of this book.

First published on Jan 10, 2010. Last updated on: Jan 10, 2010.

Comments (9)

Leave a reply »

 
 

Hy
Thanks for this wonderful and true story!

Daniel

 

Nice post. Thanks

 

Your example is flawed,

Dave was concerned about the deadline and the time it would take to evaluate the correctness of any change he made in the design of the software. He has no timely or repeatable means of doing this. So Dave added the feature without changing the design.

If Dave was documenting the design and the code then he could analyze it and see where he would have to make changes.

If there is documentation, if there are pre- and post-conditions (a.k.a. guards/design-by-contract) in the code, then it is repeatable.

her tests evaluate the correctness of every feature she adds.

You can do that with your brain and your own powers of reasoning…

Your example assumes Dave is an idiot. It wouldn‘t matter if he knew how to write more unit-tests, he would probably screw that up as well perhaps by not writing enough unit tests or missing the edge cases or whatever.

You‘re making it seem as if up-front design and lack of unit-tests means you‘re a moron. There are many software projects that used reasoning and thought first instead of tests first to reduce the number of defects and to produce almost error-free code.

Remember: tests can‘t prove the absence of bugs.

 

@Rudolf O.

You‘re making it seem as if up-front design and lack of unit-tests means you‘re a moron.

I wouldn‘t automatically say that – if you don‘t have test coverage and if you plan for requirements that aren‘t going to change – you‘re necessarily a moron, Maybe you don‘t know any better.

Remember: tests can‘t prove the absence of bugs.

Unit testing has nothing to do with proving the absence or presence of bugs. It is nonsensical to make such a statement.

Unit testing is about codifying the required behaviour of your software in such a way that is repeatable – and by that I mean without supervision and and that can be automated. TDD means you start by thinking about what requirements are and codifying them ins something that evaluates the correctness of the software.

To quote Giles Bowkett:

Judging unit testing by its ability to find bugs is like judging your pet dog by his or her ability to spin webs and manufacture silk out of his or her ass.
 

Loved the little story. So true. Since I started doing TDD, I‘ve been a real monster against my code. Ripping guts out and moving organs around.

That all sound very gory but in the end, I have a better architecture that suits the need of the client.

 

Your example is really flawed in that it takes many circumstances in the real world out of scope. For example you assume that you as a developer can make refactorings and design changes on every state of the project, which means also in the maintenance phases after it has shipped. But this is mostly not possible because you have to change documentation, DB-Schema, UI etc. as well and this has huge consequences and therefore is mostly denied by your product/project manager. So in essence you have to stick with your initial (until first shipping) design in waterfall and TDD scenario and therefore TDD doesn‘t really pay off that much.

 

@Michael S.

This article is an illustration of how employing TDD removes some of the barriers developers have when considering design changes. You‘re right in stating that there may be other reasons why design changes are difficult.

However, the reasons you state are no less relevant to quick hacks. Even hacks need to be documented. Schemata are just as likely to have to change as a result of a hack. In relation to UI, this is usually the first tier to suffer as a result of a hack – let's just get the user to do this differently, problem solved!

So in essence you have to stick with your initial (until first shipping) design in waterfall and TDD scenario and therefore TDD doesn‘t really pay off that much.

And what happens after you‘ve shipped and you‘re working on the next version? Waterfall is a joke, it always was. From Wikipedia:

The first formal description of the waterfall model is often cited to be an article published in 1970 by Winston W. Royce (1929–1995), although Royce did not use the term “waterfall” in this article. Royce was presenting this model as an example of a flawed, non–working model.
 

... ss=“delicious“Why TDD: Freedom to refactor(tags: a href=” ...

Leave a Reply

Your name
 
Email
 
Website
 
Comment

You may use Textile notation here
 
 

Please perform this simple arithmetic test to prove you are human
 
 
 
People I like
Other sites