The Ghost of Source Code Past

How to refactor code zombies

Ceyla Ponders
Oct 21, 2019 · 4 min read
Image for post
Image for post
Photo by neil kelly via Pexels

If you’ve worked in software engineering for any length of time, you’ve likely come across at least one instance of this: scary code nobody wants to touch.

Why Must I Slay This Dragon?

There’s a very straightforward reason why some code needs to be refactored.

It’s too painful to maintain as-is. Nobody knows what the code does. If you attempted to rewrite the code from scratch, you might miss several important (but obscure) edge cases everybody has forgotten about.

Refactoring in a Nutshell

The entire refactoring process looks like this:

  1. Make one simple change.
  2. Make sure you haven’t broken anything.
  3. Repeat.

Let’s dive into each of these steps.

1. Make One Simple Change

Because you’re working in a scary codebase, you need to find ways to limit the risks you’re taking.

Making small changes that are easy to understand is relatively safe. Avoid making large, sweeping changes that may have some incorrect assumptions baked into them.

Some examples of simple changes:

  • Renaming a variable.
  • Moving a function from one class into another class.
  • Pulling a couple of lines of code into their own function.
  • Removing a dependency (assuming you’ve already removed all calls to that code).
  • Creating a new, empty package or binary.

2. Make Sure You Haven’t Broken Anything

Depending on the codebase you’re working on, this can be a non-trivial task.

Add test coverage before you refactor the code. That way, you can make sure that the behavior before and after each refactoring step is the same. Use code coverage tools to make sure your tests exercise all code paths.

If you’re unlucky, you’re working with code that’s either very hard or impossible to test automatically. I’m sorry to say that you’ll have to test your changes manually.

If it’s painful enough, you might want to come up with some creative ways to dig yourself out of this predicament. Are there any workarounds? Unconventional approaches for testing your code?

3. Repeat

Ideally, you’ll commit to your local branch after every refactoring step. In practice, you’ll likely bundle several changes together.

If a single refactoring step touches many files, I usually try to get that change checked in to the main branch as soon as possible. The more files you’ve changed, the higher the chances that you’ll run into merge conflicts if you wait before checking in.

Code reviews with 50+ files in them can be annoying for teammates to review. If all you did was to rename a function, and thus all 50+ files were changed in exactly the same way, then the code review becomes very straightforward and quick.

If you’re working in a scary codebase, you want to avoid unnecessary risks. Large, convoluted code changes are a bad idea. Make sure it’s very easy for your teammates to understand all the changes you’ve made.

Beware the next deployment: avoid accumulating a giant mountain of changes between deployments to production. The more changes go into production all at once, the higher the risk.

Why Refactoring Is a Treat, Not a Trick

One of the key reasons I enjoy refactoring so much is the unpredictability of it.

You’ll discover secret relationships and hidden gems. Some of the code will make you laugh. Other code will make you cry inside. You can learn from other people’s mistakes and compile a mental list of “what not to do”.

There are many creative paths you can take on your refactoring journey. As you gain more experience, you develop better hunches as to which path will take you to your goal most quickly.

Getting Stuck in the Maze

I don’t always know where I should start. So, I just pick a place and try some things.

If I feel extra stuck, I start by simply updating the code so it follows my team’s coding standards (the rules that describe what “clean code” looks like in your team). As I make cleanup progress, I become aware of additional things I’d like to change.

Sometimes, I end up realizing that I went in the wrong direction. But even when that happens, I’ll have learned some important things about the codebase I’m working in. It’s not wasted effort.

If anybody tries to tell you that the next step is always obvious, they’re either inexperienced, somehow know stuff that nobody else knows, or they are lying to you.

You’ve Tamed the Monster

Congratulations! Enjoy it while it lasts.

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store