The benefits of continuous micro-fixing

In software engineering, “micro-fixes” are these small fixes that you make to the code of a software product. Like the fixes of defects of all types and sizes, they are synergistic: the overall improvement is always greater than the sum of the individual ones. Also, continuous micro-fixing decreases the future cost of maintenance and support, and this in turn increases the amount of resources that would otherwise become unavailable. Ignoring small defects or starving them of resources is a false economy, because their impact on the product, and therefore on the customers, is often disproportional; and their eventual fixing, necessary or simply desired, will cost much more and deplete the availability of resources for other work like the development of new features. Continuous micro-fixing improves quality, decreases costs, and frees up resources.

An example: a few years ago, I happened to find a bug in a routine that had been recently modified as part of bigger defect being worked on. In effect, this was a bug in a fix. The problem code was just a few lines long. The bug was not currently provoked, but a change in the routine’s use would result in incorrect data, with potential bad consequences at customers. Circumstances meant that I had to raise a new bug report or the information would have been lost, but I also notified the developer who had modified the routine, pointing out the problem, and stressing the importance, in my opinion, of an immediate fix—at that point it would have taken no more than an hour to fix and test. Instead, he ignored the bug on the ground that it wasn’t ‘live’ and wasn’t affecting a customer… A year and a half later, a customer’s problem was eventually diagnosed as being caused exactly by the bug I had reported. Besides the intangible of an irritated customer, this had so far cost 25 to 40 times more (leadtime was much greater) just to get back to the bug report than fixing the bug in the first place would have been… and we still had to fix it and deploy the fix.

In my reasonably long career so far, I have often encountered similar scenarios. Usually there are plausible excuses to avoid doing the work, like lack of resources or time pressures. But these are actually fallacies: studies have clearly demonstrated that the earlier you fix a defect, the dramatically less it costs. In Code Complete [ref1], the author writes:

[…] focusing on correcting defects earlier rather than later […] can cut development costs and schedules by factors of two or more (McConnell 2004).

If you reverse the findings, the conclusion would be that if you don’t take the time and make the effort to fix defects then you will continuously lose time and resources as you move forward. Time spent fixing is always an investment that pays off many times over—and this includes micro-fixing.

So, what are micro-fixes?

Let’s have a look first at what a micro-fix is not for:

  • A defect whose cause is unknown and takes time to find.
  • A defect found but whose fixing is complex or delicate or risky.
  • Major problems found during a code review.
  • The review and copy-editing of a whole set of UI message strings.
  • A single defect, which when examined, turns out to be a “class” defect (many instances affected).
  • Medium to large refactoring which would take days to implement correctly.

On the other hand, these are good candidates for micro-fixes:

  • A bad message string (typos, grammar, ambiguity, terminology, etc.).
  • A compilation warning.
  • A missing boundary check.
  • A buffer under/overrun.
  • A localised resource leak.
  • The undefined behaviour (or misbehaviour) of an edge condition.
  • An incorrect test condition.
  • An incorrectly nested set of conditional statements.
  • A wrong calculation, pointer arithmetics, array index access, etc.
  • Minor refactoring.
  • Many language or technology-specific small problems, e.g. COM incorrect AddRef‘ing and Release‘ing of objects.

I would also include in micro-fixes these small changes which are not fixes as such (there is no actual or potential operational defect), but which work to prevent problems from appearing by improving readability and clarity. For example:

  • Inserting or fixing comments.
  • Documenting a function’s parameters.
  • Reformatting code.
  • Re-arranging a complex conditional sequence.
  • Giving a symbol a better name.

The criteria are that…

  • … the defect must be small (although its potential impact may be large), e.g. a few lines of code;
  • … the overall time necessary to fix it and test the fix should be short, e.g. from a few minutes, to a couple of hours maximum for the largest micro-fixes;
  • … the defect, the fix, and the results, are entirely understood.

If a defect looks like it is convoluted, or the effect of a fix is not entirely determined, or there is a risk of regression, or simply you don’t entirely understand the defect, then it’s better to raise a bug report and let the matter be handled that way—all genuine bug reports are important; it’s only their priority which may need to be adjusted.

Should you raise a bug report for a micro-fix?

Typically, no (but see above), as it is often the case that the life-cycle of an official defect (reporting, triage, allocation, implementation, testing (which may be impossible or meaningless from QA’s point of view)) will consume more resources than fixing the defect itself would (many times over in some cases); so it’s not worthwhile in these cases.

Also, for some types of defect, reporting them could be deemed facetious—and arguably this would be reasonable.

If the defect is reported, another risk is that it will never get worked on: its small size, mistaken for low importance, means that it is forever relegated to the bottom of the pile, with more “important” defects continuously prioritised ahead of it—we have “resources starvation“. Too many such reported defects, or too many more “serious” defects, only aggravate the situation. There are a few potential solutions to that problem, and they all involve shuffling priorities to break the “starvation” process.

(Worthy of note is that resources starvation also happens for defects bigger than those of micro-fixes’ yet still comparatively small. The solutions are the same—but I digress.)

Traceability

So, typically you would not raise a bug report for a micro-fix, but you still need traceability:

  • If you are working on an existing bug, then micro-changes can usually go under its umbrella as long as there is some subject matter connection, even when the defect is in a different area. This should be noted in the bug’s log, and the version control system will keep the record of changes implemented.
  • If you are working on a new feature or some improvement task, then there will usually be a process in place to record progress—use it.
  • If the micro-fix is completely outside the area of work you’re currently involved in, then it is usually possible to tag a change with “maintenance” in the version control system.

A rule of thumb is that any change to the deliverables of the product (e.g. executable code) must be traceable.
For any other change (e.g. internal code documentation), use your judgment, but err on the side of caution.

Conclusion

The impact of micro-fixing ranges from small (e.g. a typo which doesn’t change a message’s meaning) to disproportionally big (e.g. a very small defect with a very big effect), but cumulatively they always make a big difference. Unfortunately, tackling the defects is often dismissed because of a perceived lack of resources, or because the benefit is not immediate (fixing a reported problem).

Of course, micro-fixing contributes to ‘total quality’, which is an asymptotic goal in that it can never be reached but should always be aimed for.

But more prosaically, the benefits of continuous micro-fixing include sustained improvement, easier maintenance, the avoidance of future problems, maintaining or increasing the availability of development resources in the future, and even the serendipitious fixing of currently reported defects—all of which is often underrated.

Most developers do some micro-fixing as part or their work, but this can be implicitly or explicitly discouraged. Instead, to reap the benefits, this should be actively encouraged from higher up. For instance, suggest that developers spend up to 10% of their regular time on that—time easily recouped, with interest, later on.

[Update 2014-11-26] I am re-reading Code Complete by Steve McConnell [ref1]. Steve points out that the topic of code construction has been neglected (to the detriment of software development in general), and I found the following small section in the preface rather resonating with my point of view. The two highlightings are mine, drawing attention to these key sentences in their full context. (I hope that I didn’t require permission for this longer quote.):

Construction Is Important

Another reason [see book for details] construction has been neglected by researchers and writers is the mistaken idea that, compared to other software-development activities, construction is a relatively mechanical process that presents little opportunity for improvements. Nothing could be further from the truth.

Code construction typically makes up about 65 percent of the effort on small projects and 50 percent on medium projects. Construction accounts for about 75 percent of the errors on small projects and 50 to 75 percent on medium and large projects. Any activity that accounts for 50 to 75 percent of the errors presents a clear opportunity for improvements.

Some commentators have pointed out that although construction errors account for a high percentage of total errors, construction errors tend to be less expensive to fix than those caused by requirements and architecture, the suggestion being that they are therefore less important. The claim that construction errors cost less to fix is true but misleading because the cost of not fixing them can be incredibly high. Researchers have found that small-scale coding errors account for some of the most expensive software errors of all time, with costs running into hundreds of millions of dollars (Weinberg 1983, SEN 1990). An inexpensive cost to fix obviously doesn’t imply that fixing them should be a low priority.

The irony of the shift in focus away from construction is that construction is the only activity that’s guaranteed to be done. Requirements can be assumed rather than developed; architecture can be shortchanged rather than designed; and testing can be abbreviated or skipped rather than fully planned and executed. But if there’s going to be a program, there has to be construction, and that makes construction a uniquely fruitful area in which to improve development practices.

[ref1] Steve McConnell. 2004. Code Complete – Second edition. Microsoft Press. ISBN 0-7356-1967-0.

About Philippe Lasnier

A French- and British-educated professional software engineer with over 33 years of broad experience and a solid history of developing high-quality software for large and small companies across a range of applications and different industries; particularly experienced in C, C++; the development of middleware, internal components, core code, and APIs; solo, in a team, or as lead of small teams. Recognised for high-quality development, great attention to detail, keen analytic and investigative skills. Bilingual, English and French, just in case you were wondering. Philippe currently works for Spirent Communications, but in any case, the opinions here are his own.
This entry was posted in Software engineering, Thoughts and opinions and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s