Tips on Refactoring Large Pieces of Code

Hey everyone, Happy Halloween! I was planning on having a post sooner than this but having been working on a huge refactor project at work, my brain has been a little fried and time limited. I've developed a few useful skills, especially after reading Clean Code by Uncle Bob Martin. The project at work was dealing with a couple files that totaled up to over 6000 lines of code and was by no means a small task. While I can't talk about what it was directly, I can talk about what some of the experience was like and some takeaways.

Starting off, if you’re going to take on a refactor project on some legacy code, the first order of business is to ask yourself if it’s worth it. It can take 2-3x longer than what you think it will, and if you do it wrong, you’re going to be out that much time and it might be in a worse spot than when you started. On the flip side, you can find yourself with code that’s much easier to manage, maintain, and expand.

Here’s a few tips on some things I’ve learned from this experience, in no particular order.

The first one is to understand your end goal. When you first take on a project like this, you need to have some idea of what the new functionality is going to be. This could be giving yourself the ability to abstract out common functions from, say a hardware class, and allow yourself to create interfaces that you can create new, similar classes of a similar type with different implementation. By fully understanding the end goal, you have a better idea of what the task is ahead, and how to better approach it should things get hairy.

Next, I would have to say is spend time reading and understanding what functions call what. In my case, there were calls that went about 7 or 8 function levels deep, and by the time I got to layer 6, it called a function with a similar name to layer 3, but with a totally different meaning… This is something you almost need to laugh at and keep going, but having this understanding is key when you start to rearrange functions.

This next one saved me a ton of headache. If you see the same chunks of code somewhere, stop what you’re doing and move it to a function. By doing so, you’re essentially using the Boy Scout’s rule that was explained in Clean Code: “Leave it cleaner than you found it.” This rings true here, and it’ll save you some stress because it allows you to shrink a portion of the code, know exactly what it does, and start to get some consistency.

If you have a whiteboard or some paper and a writing utensil, don’t be afraid to use them. Having the mental maps is great. You can move quick, know what you’re doing, and quickly trace things back. What happens if this drags on for over a week? Two? A month? If that’s the case, you’re going to wish you had written down how the link to a function worked instead of having to waste time relearning what it did.

Use source control, be on a branch, and commit often. When you’re out on your own branch that no one else is touching, you’re basically in the wild west. If things work/compile, do a commit. If you rewrote some functionality or created some new functions, commit. What this allows you is twofold. You get to have a backlog of when things were working, and you can track your progress. Seeing the pile of work is always good to keep the motivation going.

Attempt to split code early on. For my case, I was working with code that controlled hardware, but also talked to our main system. All of it was in a single file, and it was a mess. One of the first things I did was moved the hardware code to a hardware class, and then kept the class that was supposed to interface with the hardware, free of any direct hardware calls that weren’t through the hardware object. This also sets you up for being able to create the interfaces I had mentioned earlier, especially since you’re essentially writing your own wrapper for the API that controls the piece of hardware.

If you’re the type of person that enjoys Test Driven Development (TDD), or it’s required by where you work, now is the perfect time to work on creating tests. You’ll be able to say if something breaks much faster, and have a good idea on when things change, what breaks what, and the structure of the code as you write it.

Try to keep the code in a compiling state. I didn’t do this early on, and I felt as though I had shot myself in the foot. Things weren’t working, my IDE was showing me a sea of red squiggles, and I felt no matter what I could do I wasn’t making any progress. This is going to kill your motivation early on, and it’s gonna suck. Don’t let this one happen to you.

Clean Code brought to my attention the worthlessness of comments. If it’s for an algorithm, it’s one thing, but if it’s for something else, see what you can do to have it “write like fine prose” as Bob Martin would say. By doing so, you can squish a couple bugs, and prevent logic errors from ever occurring. Tips for this would be name all your variables with nouns and functions with verbs but be descriptive. Try it with new code you write, and you won’t go back.

Be careful of burn-out. It’s real, and a project like this can make you feel like you’re going from a sprint to a crawl in no time. Take care of yourself outside of work. Exercise, spend time with family/friends, but don’t work on this project outside of work unless you absolutely need to. You’ll start burning yourself from both ends and the result is never good.

Finally, take a break. It’s a lot of mental exercise trying to work on something like this, and it’s not the kind of project that’s good to do when you’re tired. Sure, caffeine helps, but there’s a point where you get less benefit vs talking a walk around the office, walking outside, getting some sunlight, etec. That might be how the code ended up in this spot in the first place, and if you’re adding to the problem, why refactor?

That should do it for this post. I’m on the tail end of this project, and I’m hoping to be done with it in the next week. The whole reason I started this was to add functionality in and having the new code working is like having a breath of fresh air. I hope that when you take on a refactor project like this you have as good of luck as I did, and you don’t fall into the burn-out loop. If you want to see more on refactoring, do yourself a favor and read Clean Code by Bob Martin. It’ll give you some excellent pointers (pun intended) and you’ll have a better understanding of what “Clean Code” looks like at the end.

 

Catch ya in the next one!

-TJ