by Leon Rosenshein

Writing Legacy Code

One of the people I regularly ready is Tim Ottinger. His writing has either put into words things that I’ve felt but hadn’t figured out how to say, or said things that I’ve said, but in a much clearer/more powerful way than I have. His recent post is one of the former.

One of the dominant, less-disciplined, processes that programmers follow is:

  1. Write a bunch of code (being very careful, of course)
  2. Edit it until it will compile.
  3. Debug it until it gets the right answers.
  4. Look it over for other errors and correct them.
  5. Send it off to code review

If they write tests, they usually do so between (4) and (5).

Notice that by performing steps 1-4 first, they have placed themselves in the legacy code situation.

You can read the long form version here. That article has a lot to say about TDD, and, as usual, I agree with all of it.

But what I realy want to talk about here is New Legacy Code

One of the dominant, less-disciplined, processes that programmers follow is: 1. Write a bunch of code (being very careful, of course) 2. Edit it until it will compile. 3. Debug it until it gets the right answers. 4. Look it over for other errors and correct them. 5. Send it off to code review

Or more specifically, the fact that so often, we do it do ourselves. I see it all the time. Code that gets more and more complex as time goes on. Where the lines between domains blurs and functions start to do very different things depending on what parameters they’re called with. Where abstractions start leaking details up and down the call stack. Making changes (and testing) harder and harder as time goes on.

It starts with little things. Someone adds a special case based on one or two parameters, or if we’re in some particular state then skip a step. After a while the code starts looking like an arrow with all the nested conditionals. Instead of refactoring isolating things we make new connections to a database or call time.Now() directly. We take a function that did the one thing that was it’s name but add things to is until a better name would be doTheOldThingThenDoTheNewThingUnlessConditionXorYorZ().

I’m guilty of it. I get impatient. I have a problem. I have an idea for a solution. I start working on the solution. And of course, it’s not quite right, and I find myself in the legacy code situation. It doesn’t really feel like legacy code because at that moment I’ve got it all in my head, so making changes with context is easy. But months later, or even the next day, when I come back to it, all that context is gone. And I need to back my way into it.

It is undisiplined. I know better. Sometimes I forget. Usually I remember and do something about itm but sometimes I forget. Sometimes I get lazy and choose not to. Either way, I always regret when I don’t.

So go read Tim’s thoughts in his own words.

And remember that much of the pain you’re feeling when working without a net is self-inflicted.