So Scott and I are pair-programming, when we realize that there is code in our test setup that ought to be in the model. We look and find that it's not, but it is duplicated in a number of other test setup routines. Oh, no. Time to take a code improvement excursion. We know that it's bad form for test routines to contain code that duplicates the system, and this looks like a low-fidelity reproduction.
So we find the class that OUGHT to contain it, and transfer the method. Now we go on a quick excursion through the code base and find the code that actually does the work in the middle of a fat method in a UI code-behind. Deep sigh.
We change the production code so it is using the model, including our new code, correctly. Pop the stack, continue. Then we find (via resharper) the same code duplicated in a dozen or so other places in production code. Take a deep breath, push the stack again.
We move through the code base simplifying a bunch of methods by replacing the duplicate with a call. In the course of doing so we see a few very puzzling uses. We realize that this code was modified ever-so-slightly to have a slightly different effect. Deep breath, stack push.
We add the new method and fix the code that duplicated it. We mention to each other how much cleaner the code is with some of this cruft removed and replaced with a simple method call.
We find a very strange bit of code in the setup for a test on a report. We can't imagine it ever working. With the test setup corrected, the test fails. Push the stack. We dig through the test and find that it in fact did not work right, relying on a failure in setup to produce a result that looked good if you squint at it just right. We call our Customer and ask how it should work. Looking at the setup and the test assertions, he can tell it is wrong and never should have worked as specified. He corrects the spec, the test runs green.
We get it working, watch all the tests run green, smile at the amount of code we've cut out of the system and the report bug we've fixed. Then we realize that we just did that in our feature branch and not the master branch. Our next merge is going to hurt.
Day is over, goodnight to partner, supper with family, band practice, and back to email and blogging for a little while. Tomorrow we go back to popping the stack.
It is past my bedtime on a Wednesday night and I'm thinking about code. I need to get some sleep so I can hit the ground running tomorrow. I have a personal holiday coming up soon, and want to get some real progress while I can.
These days can be fun and trying at the same time. We look forward to the whole code base growing cleaner and tighter over time. I get a little burst of perverse joy at figuring out what bad code is doing, and a warm glow when we fix it. I worry when I realize that we still have an underdeveloped code system. I worry when we will finish our assignment.
I know darned well that cleaning the code is part of working in the code. The approving angel on my left shoulder whispers, "Code must be unique. Duplication is decay. Unique code is clean code."
A disapproving voice whispers from my right shoulder, "Code that works now is worth more than code that will work eventually." Maybe I could have gone a little further before taking on this effort. In my defense, it was all green when we started refactoring, but I don't want to miss the coming release.
This is the life of a software developer working in code that holds on tightly to its contracted big-bang origins. We've worked wonders this year, and yet wonders remain to be worked.
... to be continued ...