#45 Fallacy of Sunken Code pt. II
This is post #45 of my #365 day series.
I know you may be over it, but having spent the last week rewriting bad code, this is still a thorn in my side. Ok, so what’s more is there left to say about throwaway code? Let’s go through the sunk cost dilemma that many engineers have to go through when evaluating what to do with bad code. There is the tendency to want to take the path of least resistance. Heck, I’m definitely guilty of this. However, the issues with bad code (or bad contract language) is that the problems are compounding. The common phrase we hear is “garbage in, garbage out.” What’s worse when we build on a foundation of bad code is that anything we put on top of said mound of garbage, will inevitably be more garbage.
“Tony, you’re such a negative ninny. Not all code is bad code, and sometimes good enough will do right?”
I had an amazing moment today where I pasted a module I had written maybe two years ago into a new app and it worked, FLAWLESSLY. Why? It was stateless and made no assumptions. It was descriptive about what the inputs were and what the expected outputs would be. That’s the feeling that we should be used to. It should be the norm, not the exception that I feel when moving code over. When we stack code on top of bad code, we’re not saving any actual time, because we’re going to pay for it. It’s like riding motorcycles, it’s not about if you will drop your bike, it is just a matter of when and how fast you will be going when you do.
Don’t get me wrong. The decision to re-write code is a tough one. I spent two days trying to shoehorn bad code into a new app when I finally decided enough was enough. It was like building on a house of cards. I’d used the old code that was janky, and therefore anything that touched it, interfaced with it, was also janky. I’d spent all this time writing new code around bad code. What a waste. Or was it? I like to look at the silver-lining in these situations and at least believe that my brain’s ability to recognize crap code has at least improved from the ordeal. I’ve also gotten to know the software a lot better and improved certain aspects of its architecture that would’ve otherwise been difficult to discern or reverse engineer if I hadn’t spent all that time shoehorning. Does this make it all better? Heck no. I could’ve spent that same amount of time fixing bad code on stuff that matters, like more R&D on complex algorithms.
So what are the considerations that an engineer should take into account when determining whether to rewrite a certain portion of code?
- Code Readability — If the code is really difficult to follow, chances are you should rewrite it. If you need to rewrite the function names and load the heck out of it with comments, then so be it, but don’t just leave it there. My rule of thumb is if it takes me more than 3 passes to understand code, then it needs to go.
- Extremely verbose code — When files get unwieldy, that’s when my spidey senses go off and I think about refactoring the code to make it more scalable going forward.
- Little to no error handling — I’ll even take the entire logic wrapped in a try/catch (I won’t but it’s a step in the right direction), but poor error handling tells me that the person hasn’t thought through the various points where things can fail, and so I expect it to fail more often.
Those are just some of the core considerations I think about when deciding whether to rewrite code. If I think of any more, I’ll be sure to circle back and update this post. Or heck, I might even make a part III.