Tuesday, November 24, 2009

Partial Payment

So we have this piece of code. It's been around for a while, and it's been hacked on by a number of people. Some of them knew what they were doing, some not so much. It started out as one thing, and then suffered from "wouldn't it be neat if we also..." syndrome. Now it does several things, mostly related. And it's getting a bit.... crufty. It's not awful, but it is definitely starting to smell a little bit. (I'm pretty sure we all have a piece of code like this!)

So the right thing to do here is go in and refactor it when we next need to make a change. In principle, no problem.

As luck would have it, I happen to be the next person daring to venture into this piece of code. I want to add something fairly simple that makes it generate a list of successes in addition to the list of failures. Should be straightforward. Oh, except I need to go do some refactoring.

My task used to be this:
  • add a method to get a list of passed tests
  • add a few lines to some pre-existing methods to generate the file and header information
  • add a few lines to dump the list of passed tests into the output file.
But because I need to do the refactoring, my task now looks like this:
  • generalize the getFailedTests method to get either passes or failures, and refactor all the calls to that method
  • add a few lines to some pre-existing methods to generate the file information (separate output for successes)
  • refactor the existing generateHeader method to give me a different header based on whether I want successes or failures or both
  • refactor out the formatting of the output so it can be be HTML (failures show up on a web page) or plain text (passed tests just go into an archive)
All these are good things, but my 2 hour task just became most of a day. Ouch!

The risk with doing a refactoring next time you touch the code is the same as the reason you didn't refactor last time you touched the code - you're just out of time. Yes, this is how technical debt grows and stays around.

So how do we overcome this? We don't have time to pay back as much technical debt as we should here, and there's a risk that I'm simply not going to add the feature because I don't have a day to give to the feature+refactoring. So we compromise. I did some of the refactoring, but not all of it, and I added my feature. Total time: 4 hours. The code isn't where it should be, but it's closer.

Just like any other debt, technical debt takes time to pay down. You don't have to pay it all at once, but every little bit you pay is helpful. So don't be afraid of how much is there. Just start paying it off, bit by bit. The goal isn't to get rid of everything crufty in one fell swoop. The goal is to leave the code you touch better than you found it. Do that often enough, and you'll pay off your debt.

1 comment:

  1. Hey! What have you people done to my pristine jewel of a report generator?! :-)