Cleaning out the code cobwebs

A couple anti-patterns I see frequently, and what I do instead.

The last few weeks I’m helping a client debug a rather old code base, that nobody really understands very well. It’s full of unhandled errors, which hide all kinds of unexpected behavior. It has a test suite that hasn’t been executed in at least two years, so it naturally doesn’t work. There are a lot of cobwebs to clean out.

Of course this isn’t my first time on such a task. And I’ve seen others work on these sorts of code bases with me.

I want to call out a couple anti-patterns I see frequently, then describe what I do instead.

  1. Merge your entire debug session.

    This happens when you spend a significant time debugging a problem. Possibly even trying different solutions, which prove inadequate. Then as soon as you stumble upon the “correct” solution, you just git add . and push.

    The result is often unnecessary complexity added, in the name of experimentation. A lot of debug logs that will never again be used. And a confused developer, who probably doesn’t really know why the last thing they tried actually solved the problem.

  2. Commit only the minimal change necessary.

    This is the polar opposite of the above scenario. You do all your debugging and investigation. Then you determine exactly what fix was necessary to make things work… and you commit only that one thing.

Why are these opposites both anti-patterns?

Hopefully it’s obvious why the first is an anti-pattern. Commiting every small change, even those that weren’t useful, just adds clutter to the codebase. It makes it harder to reason about and debug next time a problem is discovered.

But why is the second one a problem?

Because everything the developer learned about the code in the process of debugging is discarded.

When I’m debugging a problem, I do any or all of the following, as I’m debugging:

  • Rename any functions, variables, or other things that are named in a way that’s confusing or ambiguous. This makes it easier to understand next time.
  • Add documenation or other comments, any time I discover something surprising. This makes it easier to understand next time.
  • Delete any dead code I discover. This makes it easier to understand next time.
  • Add additional context to ambiguous error messages. This makes it easier to understand next time.
  • Delete redundant error messages. This makes it easier to understand next time.
  • Break apart large functions. This makes it easier to understand next time.
  • … I’ll stop here. You get the idea.
Share this