Agility Depends on Good Design and Complete Test Coverage

I have a very different approach to TDD. On my project, we hold a group design session before we write any tests or code. In that design session, we determine the object structure and bombard our design with edge cases and such. We continue modifying it on the whiteboard till it satisfies all the requirements. After we have the design, we enumerate all the tests that will ensure the implementation works as expected (considering our user requirements as well). We actually end up with a list of test names that need to be implemented.

This is one of the hardest parts of our design session. Its so easy to say…it works…just implement it. But it is the most important part of our design…proving that it works. Many times we come up with tests that bring to light issues with our design that force us to tweak it. This list of tests is absolutely invaluable when you implement the code to ensure your design does what it should.

It is only after we have the detailed design and a list of tests that prove it work that we actually begin implementation. We implement it using TDD. We write each test one at a time and then implement the code that will make it pass. When the last test has been implemented and passes, the task is done…

If we wrote the tests last, we probably would skip them, and we wouldn’t have a clear path of what to do. Our tests provide that…they give us a goal to accomplish before moving on to the next one. (We order our tests during the design session in the order they should be implemented).

I realize this is a hybrid approach and differs from purist form of TDD where TDD itself is used for design discovery. We separate our design and I find that we spend more time in design than we do coding. Writing an application is far more than just typing in the code. Typing is the easy part…I leverage the whole team for the hard part…design. The code is usually implemented in no time…as long as the design was correct. In fact, typing in the code is almost an afterthought.

TDD is invaluable to this design and implement process. Without the tests, we cannot make huge sweeping design changes in the code (which we do quite often). Refactoring tools go a long way to help as well.

The tests are the primary key to having an “Agile” codebase (one that can be easily modified to accommodate changing requirements).

In the absence of tests, you can’t change code without having the confidence it will work after the change. Tests give you that confidence. If they pass, your code will work… If they don’t, you can just roll back the changes (worst case) or fix the code so they do pass.

In the absence of Tests, changes to design are painful because you break things. You will still break code when you have tests, but you immediately know that its broke, what broke it, and where it broke. (because you just did it). If you wait a month before a tester tells you it broke, you have no idea where to start fixing it.

The design is another key to having an agile codebase… While tests ensure your changes were successful, Design allows you to make these changes easily.

In the absence of well-designed code, changes are difficult. If you don’t have a solid design to work from, (I am talking about the codebase you are working with here..) with your concerns consolidated and cleanly separated, you can’t change things quickly. The codebase must be very clean and well designed for you to truly reap the benefits of agile.

In the absence of well-designed code, TDD (or testing in general) is truly painful. You may not even be able to test a lot of your code because it wasn’t designed to be testable.

In the absence of well-designed code, further design is very difficult: You can’t “get your head around” the design. You try to consider all the things that need to be “updated” when you make a change but its too difficult because your concerns are scattered all over the system. Things aren’t simplified and consolidated, so you can’t make one change in one place…its many changes everywhere…and until you implement it and see it break, you may not even know where those changes are needed.

Maybe I am rambling, maybe I am off topic… I am just passionate about this because just came from an well-designed app built from the ground up with TDD. We had great success…design and testing were simple. We could make huge design changes in no time to adapt the application to any change they threw our way. I was blown away by our productivity. I am now on a project that was under-designed, and had very little test coverage. TDD and design were VERY painful when I came onboard. If I had not had such an awsome experience with TDD on the prior project, I would have given up long ago. However, I stuck with it. We have been at it for 4 months. The project’s codebase is now 95% covered in tests, and has been 80% redesigned and it is going so much smoother. We are finally making great progress. I am now finding that the mere 20% of the codebase that is still poorly designed is where we have all our pain. Everything else is a simple to work with.

The bottom line? If you think TDD is not working…your codebase might be all out of whack. If you have good design, and complete test coverage, Design and testing will be a breeze and you will reap the benefits of it. Otherwise, it may be a long slow (and painful) road to get your codebase where you can see the benefits. It has taken us 4 months of pain so far to get to where we are now. We are now seeing the light at the end of the tunnel and I can honestly say it was worth every second of it!


This entry was posted in Agile, Design, Test-Driven Development, Testing and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>