Fix your bugs blog image

Fix Your Bugs – The Invisible Cost of Low Priority Issues

Continuously deprioritising we-can-live-with-it issues costs more than fixing them. There’s an enormous invisible cost of letting these bugs out. A tiny bug might cost your business. 

Let’s now see how much the invisible cost of a year-old bug is.

Organisational costs

Every issue in your backlog requires management time. That might be the cost of revisiting the work item repeatedly when your order the backlog. Or, you’d be asking the team to reproduce it several times because they might have become obsolete already. But the highest cost is the one your disappointed customers pay, waiting for this fix release after release. 

If you do the math on the efforts spent on deprioritising a bug versus what would have cost to fix it when the team first found it, you’d be amazed by the size of that invisible cost.  

Among the dozens of thousands of work items that I’ve been analysing over the years, an average one-year-old bug needs 50 maintenance interactions.  These are any administrative, technical assessment, testing or any other type of work done to keep that single item in the backlog but not moving it forward. Fifty administrative interactions can be 1 hour, but if it requires reproducing a bug and discussing it at Sprint Planning several times, it could be hundreds of hours wasted talking instead of investing them in higher quality.

There is a concept about cleaning backlog from stalled items regularly. Removing bugs from your backlog is nothing but sweeping the issue under the carpet. What’s worse, though, is that the first place where your customers will look is right under your rug. Never hide issues. Fix them immediately.

The evolution of bug fixing 

Software companies introduce testing last in their processes. First is the cowboy development phase aiming to launch a product asap. Then comes the marketing phase, followed by a tiny controlled team growth after the initial launch to rewrite the product a couple of times. At a particular moment, the team realises the time might have come to involve testing as well. 

Whatever they say, nobody loves testing. It’s the notion of bad news that nobody wants to hear, even though we’re all aware it’s for good. 

Fixing bugs is even more unpleasant for developers. It’s not a creative activity – it’s reactive and tedious, especially if it’s somebody else’s code. 

As a portion of the whole work, testing is perhaps 20% of the total work, if not less, in that first kickstarting phase. The team is only focused on developing new features. Testing is done by the product team or, worse – by the customers. 

Integrating testing decreases the work on new features significantly, as suddenly, a ton of bugs are recorded. The team is grateful that someone will finally take care of their code, but at the same time, it’s possible to get upset by the number of bugs poured over them every day. There could be sprints only with bug fixing, which certainly affects the team motivation. On average, the bug fixing would be more than 2/3ths during that phase, and this is when the team would start to deprioritise bugs. Stressed by the fact that no new features achieve noticeable progress, it’s natural to react like that. What’s important is that the team must be highly aware of the risks of those decisions. 

Over time, as the testing process matures, more tests are automated, DevOps practices get in place, and the team becomes more confident in making changes – the testing can decrease to about 1/3th of the total effort. And it would be a lot about writing and maintaining automated tests. That’s an optimal rate as long as the tests prevent production issues as early as possible.  

Now, read that last sentence again. 

It is a common (mis)understanding that testing prevents problems. It doesn’t. A well-established testing process can inform about critical issues as early as possible, but someone (else) still has to decide to fix them.

The priority of a bug

Prioritising a bug is even more complicated than prioritising a feature. All of us working in software development are in a love-hate relationship with bugs. If we could hide bugs rather than fixing them, that’s what most teams would be doing, and yet, we keep seeking more and more efficient ways of exposing them.

Automated testing has one great privilege in comparison to manual testing. A bug from an automated suite always has critical priority. Planning, development and support of automated tests are costly activities. Hence any bug found by automated suites and in them is taken care of first thing in the morning. That’s why it’s so critical that the framework is highly maintainable, the tests are stable and not flaky, and there are dedicated engineers to keep the tests and the framework in shape. Most importantly, the team has made this a policy, and no one steals those engineers for anything else, which is a typical bad practice.

The forgotten ones

There are types of bugs that are consistently disregarded. And their invisible cost is the highest one because those are usually considered small, low severity inconveniences that aren’t worth the technical time to correct them. On the contrary, they accumulate wasted time and build up annoyance day after day. 

Cosmetics

UX is the first thing your customers notice. It’s the outstanding UX that sells, but the lousy one that will inevitably drive your customers away. 

Remember the saying about the first impression? There are many people that, luckily for all of us, don’t believe in this. They know everyone deserves a second chance, and there is sufficient technical time to get to know a person for real. When we talk about a product, especially if we’re supposed to pay for it a significant amount of money, which forces us to use it, the first impression is everything.

I uninstall apps because of the colour scheme and the login screen, or because you can add something but can’t edit it, and I blame them for wasting my time installing the app in the first place. 

Cosmetics is everything. And usually, it’s not just cosmetics but some pretty illogical behaviour. Imagine a table that could sort on all but one column. Bugs like these are just bad for our mental health, especially if you’re a tester by heart like myself.

It’s only in the test environment

Another class of issues that get postponed often are the so-called testers’ bugs. These things might not affect the general user experience but are time-consuming for both manual and automated testing. 

The argument is always that the customers won’t have the same experience. Let’s start counting again.

Imagine there is a UI automated test suit. It is scheduled to run every night. There is an issue that we have deprioritised as a test inconvenience, and a couple of additional clicks bypasses it. 

Let’s see why deprioritising such bugs costs so much more than fixing them. 

UI tests are unreliable, slow and heavy. That’s why they must be implemented mainly for high-level end-to-end acceptance tests. The result of these tests is usually a release gate. 

Now imagine an urgent hot-fix we need to release asap and that the tests keep failing today at the additional clicks we do to work around the UI bug. Instead of the team focus on the hot-fix, they would now have to spend time fixing the tests. After a whole day of investigating, it would turn out to be a problem related to a browser update, and the team would need to rewrite the tests. The quick solution at the end of a highly stressed day would be to disable these tests to pass the release gate. 

This day will be unforgettable for the whole team but not as a dear memory. They will go home with the sour taste of wasted time and efforts, lack of adequate decision-making and overall disbelief. Most probably, that was not the first hectic moment like this. 

The customer will remember this day as well, as the team was so late to deliver the hot-fix. For sure, there had been consequences for them and their end-users as well. The so challenging to build trust has now cracks, which the customer will start using on any possible occasion. 

The invisible cost is much bigger than the obvious – it’s the low team morale and lost motivation, and the broken customer relationship. 

The additional clicks, even if they work flawlessly, are extra execution time. If the tests run every day, moreover if they’re part of the build sanity suit, and these extra clicks take a minute in every test, we’re wasting hundreds of hours every year. Instead of spending a couple of hours once to fix and verify a minor inconvenience, we choose to waste hundreds of hours every year. 

Cluttering our routine work with unnecessary workarounds that seem to be too menial to take care of is all costing our ability to be agile, productive, and efficient. Furthermore, they eat the time for what’s really business-critical.

Technical reasons

Now, we have to admit that there are bugs indeed that, even I, tend to postpone. What’s crucial in those cases is to evaluate the actual risk.

The two most common reasons to deprioritise a bug are if it’s an anomaly or the fix might be in legacy code.

Anomalies are impossible to reproduce. There is no logical explanation why they happen. It’s severely time-consuming to investigate them. There are no immediate actions to fix them but attempt to expose them more consistently or eliminate the possibility to occur. Sometimes, it’s wise to change the business process, than fixing an anomaly.

If the business risk of that anomaly is manageable, we can keep it for the record and future reference, but most probably, we won’t invest any more efforts. It’s inevitable, though, that the anomaly will show itself again sooner or later, or an unrelated change will put it in the spotlight.

Legacy code is the developers’ nightmare. There are modern software systems that work on top of 30-years-old components. No one wants to touch them. Replacing them means rewriting the whole system, and there are no resources or a winning business argument for that. Dealing with such issues is politics figuring out which integrated system by an external vendor will work around the legacy issue. 

Apart from these valid cases, deprioritising minor bugs is an illusion – there is time to fix them right away! 

There is time to fix them. Let’s do some more math. No one works 8 hours on designing new features. What’s worse, you’re missing motivational opportunities because working 78 hours on a complex algorithm without much success can cause a substantial motivational and productivity drop, which fixing a tiny bug would overcome and perhaps even boost the productivity. 

Otherwise, the issues will get obsolete, making an effort to report them as a waste initially. Very often, the bugs indeed become outdated – if we wait a couple of months, the bug will be gone because someone would have done some refactoring, or the whole feature re-designed or removed. 

During these couple of months, though, many customers would start thinking that you are providing a poor service and aren’t worth it.

Bugs are not features

The insanely dynamic markets are pushing development forward, making unimaginable compromises with quality. We see horrible bugs by the technological mastodons every day, some of them causing real-life tragedies. The worst thing is that the end-users are getting more and more used to poor software quality. The word bug is not a weird technical term anymore but rather an expected characteristic of the software. It’s very convenient if you think about it – everyone in the world now knows that software products have bugs. 

We’re so used to bugs that nobody realises that it’s much more expensive to keep all these bugs than to fix them.

The most passionate critics of poor software are the software makers themselves. It’s so curious then how, during the Backlog Refinement, everything that is not a complicated backend algorithmic issue is deprioritised. 

How to get rid of all bugs without sacrificing features?

Bugs are stains. Would you go outside with a stain on your shirt, no matter how small it is? Then why release your software with stains to millions of people consciously?

Because we don’t have a choice? Well, maybe. Some practices can help reduce the number of low priority bugs significantly and, therefore, decrease the cost of backlog management and the risk of lost customers.

Practices overcoming bug deprioritisation

We deprioritise bugs because we think that we don’t have enough capacity to fix all of them. Remember, it’s not just the fix; it’s also further testing and potential regression. The small bugs are famous for causing unexpected regressions. So, to avoid the need to deprioritise low priority bugs, we have to find a way to avoid letting them out. 

The most effective practices are Code Reviews, Developers Pairing and Developer and Tester Pairing. Code reviews and pairing are well-known but still rarely practiced. Yet, they cover the developers’ point of view. 

The source of cosmetics and testing bugs is the Product Owners, the Designers, and the Testers. 

Let them pair with the developer and do the coding (and the testing) together! 

There is an unbelievable gap between the engineering teams and everyone else. It’s proven, it’s natural, there’s nothing wrong with that. Everyone else tries to do their job so well that the developer doesn’t have any other option but create the perfect software. The problem is that this is subjective. And everyone has a different opinion of what perfect software is. Even if we comply with all Definition of Done before the development, it doesn’t guarantee that the user won’t feel something unpleasant when working with the feature. For sure, the user will do something unexpected. So instead of waiting for several phases to run before we can share the feeling, let’s sit together and figure it out while still in the making.  

Make it a weekly coding/testing session, mini hackathons, if you’d like. Find what’s best for your team so they build a high-quality feature from the first time. Such a practice has several remarkable impacts. It will increase awareness, it’s a great team-building exercise, and it will speed up the time to production for your features, also eliminating dozens of small items and hours of discussions later.

My second advice is don’t overload the Sprints (if you’re still using Sprints). Planning 100% of your team’s capacity is an awful approach for so many reasons. One of them is that you’re missing the opportunity to do some cleaning. Leave time for some ‘breaks’ – fixing minor bugs. 

Bug fixing creates good habits

Postponing small bugs is disrupting the user experience, hence the business and the brand.

They are bad for team morale – the more bugs we deprioritise, the lower the team’s motivation to write high-quality code and test thoroughly. 

Every small item cleaned out of your way opens space for the giant steps.

I firmly believe in the optimisation of the working processes. Everything that can run more efficiently must be tried. Every step in a process that we can spare, automation where possible, or one-paper project management techniques, for example, are all approaches to make our daily life easier. Establish productive routines and, most importantly, enable teams to react when unplanned events happen. Unexpected events happen every day, and all of them have critical severity and the highest priority, so get rid of the small rocks.

Appreciate every bug you find. Take good care of it. It can save your business.