Refactoring Matters

Alex McConnell
7Factor Software
Published in
6 min readMay 12, 2020

Unclean code can be a disaster. Time and time again, app development slows to a crawl or is released with crippling bugs because of the difficulty of adding new features and finding bugs with unclean code. Getting stimulus funds to people for the Covid-19 crisis was slowed dramatically by aging COBOL systems full of spaghetti code. Getting the results of the 2020 Iowa caucuses was delayed due to failures in the code to properly report the data. Boeing’s Starliner project has faced repeated delays due to bugs in their code. Medical record-keeping software company eClinicalWorks paid a $155 million settlement to the U.S. government over their failed code. These problems could have been prevented or mitigated by maintaining clean code. There are 3 main elements to having clean code: knowing and following best practices, comprehensive testing, and continuous refactoring.

Most software is like a junk drawer. Pretty much everyone has a junk drawer in their home. Some of us are good about keeping it from getting out of control and finding new places to put the things that end up in there. Others of us aren’t as good as that and end up with half a dozen junk drawers, and with a family of four, even when something has a proper place, you can’t be sure if something you’re looking for is actually where it goes, in one of the various junk drawers, or in some mysterious other place, like under your son’s bed. And then there are those of us who can’t even manage that and end up with piles and piles of junk throughout their home. Most software is worse than that.

Most software is like a junk drawer, if your junk drawer were actually one big room, and you’d never even seen an actual drawer or a shelf before. A place where your random piles of junk include your books, your silverware, your television, and your refrigerator, with everything connected to other things with cords. The cords are both a blessing and a curse. If you’re trying to find something, you can use those cords to follow the path from one thing to another, but the cords also end up getting tangled up with other cords.

Most software is like a junk drawer, and most engineers don’t even realize it. Software engineering is so incredibly complex that all of us are always learning as we go, and if all you’ve ever seen is a junk drawer, you won’t even know that there’s a better way. If you’ve never seen a filing cabinet or even filing folders, having giant stacks of paper on your desk just seems like the way everyone does things, and you’re too busy dealing with the chaos to look into finding a better way. So it just keeps getting worse. Features take longer and longer to implement, more bugs crop up when new features are added, and bugs take longer and longer to fix. It keeps getting worse until it’s so bad that stuff is falling out the back of the drawer, and you can’t open it anymore because something you can’t see keeps sticking up too high. And that’s the point where most engineers realize that they need to stop and “refactor.”

This brings us to the three Rs of software engineering: refactoring, refactoring, and refactoring. Refactoring is the process of restructuring your code without changing its external behavior. The fact that external behavior doesn’t change makes it seem to some that it provides no business value, but that couldn’t be further from the truth. Refactoring is the software equivalent of having stacks and stacks of papers on your desk and then learning about the existence of filing cabinets and saying, “wow, we need to get one of those and file all these papers away!” Yes, doing that means putting other things on hold, but since we all know what filing cabinets are and why they’re important, it’s blindingly obvious to all of us that putting things on hold to get this done is indeed essential, provides tremendous business value, and the sooner it’s done the better.

It might seem like engineers should already know about filing cabinets, so there’s no reason they wouldn’t build and use them, but software engineering is so much more complex than that. We don’t just get piles of papers, we get piles of X, where X could be absolutely anything. How does one file rocks, airplanes, or cats? And since one can’t just buy a filing cabinet for airplanes online, once we do figure it out, we have to build it ourselves.

The solution is to always be refactoring as you go along instead of waiting for it to hit critical mass. As with anything else, it’s a lot easier to organize your code when there’s only a little of it than when there’s a lot, and once the pattern for organization is in place, it’s easy to go along with it. Whenever one is writing code, it’s important to not just be thinking about how to solve the problem at hand but how to do so cleanly, and to restructure the surrounding code to best meet the new requirements. And remember, most software engineering these days is agile. It’s not agile to build a filing cabinet before you have any papers, let alone files, but it’s also not agile to keep stacking up your paperwork without sorting it into files and cabinets. It’s important not to build that cabinet too early, but it can be even more important to not build it too late, but since so many engineers have never even seen a filing cabinet, too late is far too common. It can be very tempting to get things working and consider it done, but cooking a meal isn’t complete until the counters are clean, and the dishes are done and put away.

Sadly, most engineers aren’t thinking about how to write the best code or the cleanest code. They’re so hyperfocused on solving the problem of the feature that they’re not even thinking about solving the problem of how to integrate their solution with the existing code. Because of that, when they finish solving the problem of the feature, they feel like they’re done and just jam it into the existing code however they can, just like a junk drawer. Even engineers who know better have a tendency to follow an existing bad pattern rather than establishing a good one or feel pressured by time to deliver as soon as possible.

At 7Factor, we take pride in always working to find the best solution, not just the quickest solution. This means knowing and following best practices, comprehensive testing, and continuous refactoring. When your code follows best practices it becomes easy to update and maintain, and continuous, vigilant refactoring backed by comprehensive testing is how you get there. When you follow those principles, you end up with code that is easy to extend, has minimal bugs, and is easy to debug when there are bugs.

photo credit: Cory Doctorow Tangled wires, Freegeek, Portland, Oregon, USA (license)

photo credit: Mitch Barrie File Cat (license)

--

--