The code works, but it smells funny. A simple
if statement makes the bug go away, but we know somehow we’re just masking a bigger problem. Should we take the time to figure it out? Or should we call it a day, mark the issue as resolved, and move on?
What else could I be doing
Nobody will deny that fixing a defect correctly is a waste of time. The question is whether it is the best use of my time. What else could I be doing instead of chasing down this defect?
When deciding the value of a fix, I’ve found the following considerations to be quite useful:
- Who’s code is it?
- How often is the code used?
- How critical is the code?
Who’s code is it?
Within my team’s own codebase I know I have the freedom to make changes I need. I don’t have to struggle find the ultimate source of the problem. I can instead tackle a bit at a time — writing small unit tests and cleaning up interfaces while I search for the problem. This way I know, that even if I don’t find the true source, I’ll at least have improved our code.
For code coming from another team the situation gets a bit trickier. I may have access to the code, but I don’t have the option of writing small tests, or changing anything. If I can’t actually identify the underlying problem there’s a chance my time has been entirely wasted! But if I do find the problem, there’s a good chance I can use company channels to get it fixed.
On third party projects the situation is the most bleak. Isolating the defect and providing a clear reproduction is no guarantee of it being fixed. Even if I can get an issue accepted I have no control over the timeline to a fix. I could be waiting a long time, and thus need to do a quick fix anyway. For this reason I place very little value in isolated defects in third-party code. I will often just do the quick fix and forget about it.
How often is the code used?
I don’t want to see my dirty fix applied in many places throughout the code. When I work on an issue I’ll often look at the nearby functions and search for them throughout the code. Often I see that the fix I’m applying has already been done in numerous locations or I see other fixes that I need to apply. In any case, if I see a pattern I know it’s time to do a proper fix. The time I invest now will likely be saving significant effort in the future doing patchwork to all these other locations.
Often though the code path is unique. There’s only one caller and it isn’t using any other shared code. It makes sense to apply the quick fix. The underlying error has a low likelihood of manifesting itself again. Any time I invest now may never be recuperated. No other programmer may ever be saved any time. No user may ever encounter another defect. My time really is better spent elsewhere.
The value proposition here is actually quite simple: the more the code is used the more valuable the fix. Don’t fret making quick fixes to fringe code.
How critical is the code?
All systems have critical components. While very few of us work on things like airline guidance or medicinal devices, all of use work on products with definite value. Something in our product must be the key to providing that value. Either it’s a key feature, or a core component. Knowing what these are is vital to proper prioritization.
I don’t like smelly fixes on critical components. It’s hard for me to stand behind the value of a product if I suspect one of its key features isn’t working correctly. These are also the features that people assume are working correctly. While product management, marketing, and users do understand that defects exist, they aren’t expecting them in these places.
Like all aspects of project work it ultimately comes down to a cost-benefit analysis. The biggest cost is usually how much time I’ll spend working on this. The value is often harder to quantify, but has to relate to user satisfaction with the product. When I can make an estimate of time I certainly will. It’s a lot easier to decide on proceeding with an issue knowing its cost, even if the value isn’t absolutely certain.
But when debugging defects, it’s often very hard to predict how long it will take. If we don’t really know what the true problem is, how can we estimate how long it will take to fix? I generally follow the strategy in this article when debugging. As I work through the defect I’ll either find the solution, or form a continually better impression of cost and benefit.
The key is to stifle any perfectionist tendencies; though I certainly don’t want a lazy attitude to take hold. As a programmer I must remind myself it’s all about the users of my product, not the code itself. Allocating my time to best server my users is the only viable approach.