Setting the scene...
You are building your second large TDD project for a new client. Some of the requirements are almost identical to the last TDD project. Management is aware of this and expects some form of code reuse to occur that will save budget and time. The functionality required is separated well in the code and design but is still tied to the business tier in deployment and cannot be easily isolated in binary form.
Options tried to date:
- Copy and paste all tests and production code of interest. Then tweak the code till everything runs green. Run ... 15 tests fail ... tweak ... run ... 14 tests fail ... etc.
Pros: Simple to copy
Cons: Very negative process - lots and lots of failures - start doing anything to make it pass. Feels like the haphazard development of old. You can easily miss a requirement or add something unnecessary. Test quality tends to be low and tests are poorly understood. Takes a long time to get to green.
- Copy and paste one test, fail, paste production code, pass. Repeat and stir.
Pros: Simple process.
Cons: Test order might not match original development and therefore may not flow with available functionality. Difficult to isolate relevant production code each time. Process does not always flow logically.
- Start from scratch! Write a test, fail, add code, pass, refactor. Check old tests for ideas and check old production code for implementation when stumped. Learn from the old, improve with the new.
Pros: Our beloved TDD process with all the benefits of the process. Gives an opportunity to review the old code while flowing through the new. Feels quicker and has a definite sense of moving forward.
Cons: Should be slower and could suffer from "reinventing the wheel".
The biggest benefit of TDD is the process. Reusing past successes while deviating from the TDD process appears to be counter productive since the process *is* the benefit. It helps to keep the pair moving forward and helps them to stay focused. The copy and paste techniques quickly returned to the hack it without a technique ways of old. Worse still, they did not bring the confidence of the red/green cycle.
(Better separation of the logic into deployable units may have made the process easier but would have involved more setup and deployment work for the initial client.)
This was a surprising exercise and did not produce the results that one would probably expect. Perhaps "copy and paste" reuse in TDD is like trying to eat the elephant all at once? (HowDoYouEatAnElephant)
Have you had similar experiences? How did you tackle them? What would you do differently?