A programmer, writing some new code, looks into some existing code that she needs to use. Something doesn’t look quite right. In fact, there’s a bug. Whether no one’s triggered it, or they have but their complaints haven’t reached anyone who will do something about it, is hard to say. Can she fix this code now and keep working? Or does something prevent that?
In such a situation, I would prefer to write a new test illustrating the bug, fix it, and check both the test and the fix into source control. This might take five minutes or an hour. It’s a small detour, but I feel better knowing that the code is now safer for the future.
Maybe, however, there are policies, either explicit or tacit, that prevent such quick resolution.
Perhaps there is a “ticketing” system that requires opening a formal change ticket before introducing a change. That can slow you down. It might also make it more difficult to do if you’re already working on a different change ticket for the new code you’re writing.
Perhaps someone else is the “owner” of this code, and you need to ask their permission before fixing it. Perhaps you even need to ask them to fix it. If they’re busy working on other new code, you may wait a long time. The change may seem unimportant to them.
I’ve often seen organizations that lock down their “architectural framework” code on the assumption that only their most senior developers can be trusted to work on it. Asking that something in this code be fixed might require writing up a formal justification and submitting it to an architectural review board for consideration in their monthly meetings. Perhaps before making any change you need to create design documents and get them approved. Perhaps a committee needs to come to consensus on what design is best.
Perhaps various teams have to analyze what effect the change will have on their code. To do this, they’ll need to check what assumptions their code is making. If these assumptions aren’t encoded in automated tests, this is a difficult check to make.
I’m sure there are other ways to slow down or discourage fixing broken code, but these are common ones I’ve seen.
Why is this important? If it’s easy to fix the code, programmers are more likely to fix it. If it’s hard, they may ignore it and leave a bug waiting to happen. After all, nobody will point a finger at them about a bug they happened to find and then ignored. So, bugs accumulate.
Even if the bug is important enough to brave the work of bringing it up, the delay is intolerable. They may have to program a work-around, a patch in some other place to compensate for the bug. With good intentions, this is meant to be temporary, but after a long delay, it’s hard to go back and correct this. Such patches further degrade the code design, making it harder to program and easier to create bugs. It puts behavior in unexpected places where people won’t think to look if it’s causing problems. I also crates surprises that programmers won’t expect if they’re reusing the code where the patch was hidden, causing further bugs.
I do not believe that you can prevent mistakes. The strategy I’ve found to work is to make it easy to notice and correct them. Beyond that, think about the underlying causes and try to make similar mistakes less likely in the future. But give up on locking things down to prevent mistakes.