Bugs are just a fact of life in software development: nobody likes to see them, but so many demands confound a programmer’s time that it becomes impossible to design down to every last exception. Sometimes the bugs even pre-exist in the tools that we use, the development environments, or the compilers.
However much I’m reluctant to admit it, all the same we’ve got a vested interest in keeping a fair share of bugs in the works; if our offerings are perfect then we essentially program ourselves out of our jobs. Imagine if all the schoolkids picked up every last piece of trash and wiped down all the tables when they finished lunch. What would all the janitors do?
You can prevent some bugs by utilizing certain development techniques. One of my favorites is to rename all of your variables and functions to make them distinctively descriptive and non-overlapping. This adds another couple of days to the project, but in the long run it pays off twice: first in easier maintenance with standard names. Second the process of editing and replacing catches many bugs by itself.
As I mentioned in an earlier post, another useful trick during development is to make specific plans to keep audit trails (or trace logs). I usually ask the staff to define a global Boolean called Testing that when true should cause nearly all activity to log to external files.
When persisting to a database I prefer to avoid deleting records: instead I include an “obsolete” flag and set it True when the record should be ignored. Depending on the audit requirements of your system you may even prefer to append a copy of a record for modification, so that if necessary you can always go back to prior versions of a row (note however that this strategy is quite costly from a storage perspective).
Legally many systems also need to track the identity of the user and a timestamp when any rows or fields were modified. If you also include a field to identify the module name and version of the modifying process you can greatly aid version-debugging and historical corrections.
Tracking and fixing bugs is an art of its own. Under pressure rank a bug’s squash-priority by the nature of its criticality. Certainly items that involve the health and safety of your clients, your staff, and yourself come first. Items that adversely impact production cycles are the next highest importance. Bugs that interfere with someone accomplishing their work come in third (especially if you lack an immediate workaround).
Next you will have a large hodgepodge grouping of nuisance bugs, resource bottlenecks, and business-critical enhancements. Everything else will likely go into the bottom of your priority list for “when you have the time”. A useful trick-of-the-trade is to dedicate one-half to one day each week for the lowest priority items; that way you can at least address some of them. Keep the list of unfinished items however… at some point several months to a couple years down the road you will want to revisit many of them to see if they still have merit.