This page may be out of date. Submit any pending changes before refreshing this page.
Hide this message.
Quora uses cookies to improve your experience. Read more
Robert Walker
When I find a bug, then - is a tendency just to fix it and move on.

BROADER PICTURE OF A BUG


But - it is worth taking some time to think through and get a broader picture, and ask a few questions such as

  • how did this bug get into the code in the first place?
  • Are there coding habits I have that cause problems, or ways I can change the way I code to avoid bugs like this in the future.
  • Have I got any similar code anywhere else in the program? If so - then it's worth doing a search of the program to see if any of it is buggy in the same or a similar way. Often when I fix one bug - a search like that turns up other examples of the same coding error to fix.

CODE COMMENTING OF BUG FIXES


Then - I also add notes to the code to explain the bug - as well as in my "to do and done" bug tracking - unless it is really obvious,

So, that way a future programmer (in my case, myself as I'm sole developer of the code) can see what I did and why I did it. Otherwise then - someone in the future might "fix" the code again for some other reason and in the process might remove or change the bit of code that prevented this elusive bug, not understanding its purpose.

That's part of the reason, I think, why fixing bugs may cause other bugs - because the previous coders didn't comment their bug fixes clearly enough so that when you fix new bugs, you don't know to reinstate the earlier bug fixes in the same code.

So - like all code commenting - no need to state the obvious. But if there is anything that needed a bit of puzzle over to detect the bug - or if the fix is not an obvious one - or the reason for it something you could forget in the future -  is there something I can write as a comment so that a future reader of the code doesn't have to go through that same puzzling ovr the code again?

CODE ASSERTS


I also often add an assert of some type. Well actually way I do it is

if(condition) DebugBreak();

Find that easier to work with. But it's the same idea.

So for instance - simple things - if it is an out of range array index for instance, add an assert before the line of code. If it's a null pointer that caused a crash - add assert to check that it isn't a null pointer. After a while you might do that automatically anyway, adding bound checking and null pointer checks just takes a few moments to do and you can do it while writing the code in the first place.

So it helps you get into good habits for the future also.

Usually those asserts don't slow down the program at all - so you can leave them in the release as well - so that - if in the release any of those conditions did happen - the program won't crash. And in debug build if they happen - you get a debug break in the compiler and can see immediately what went wrong.

So, lots of asserts in the code. And - sometimes you need to do checks that are quite time consuming - so those might be in the debug build only - and with a #ifdef (or whatever) to switch them on and off.

UNIT TESTS - OR - IN MY CASE - LOTS OF PRESETS


Then - well many programmers do unit tests. For myself - my programs are huge and complex - and used for creative things - such as creating fractal tunes or 3D visual patterns. My best selling program is used for creating complex rhythms.

For those - the main way I test them (not the only tests of course) - is to have lots of presets inside the program - also useful for the user - and then to test it - I go through the presets and play them or watch them or listen to them - and check to make sure they still sound the same as before.

That's taking advantage of human ability to spot a small change in a visual image or a soundscape. It's what my users care most about - that the rhythms are played correctly, that the fractal tunes sound the same in new versions - and that the visuals they made in old versions look the same in newer versions of the program.

I have hundreds of preset fractal tunes for instance, in Tune Smithy - and they demonstrate all the different features in the program for making fractal tunes. So - for a thorough test of it - I play through all those tunes and check they sound the same as before.

Sometimes I have other projects that I save for my own use for testing which are not intersting to the end user - but help to test various combinations. And every time I get a significant bug - I save it as a project - and then later on - I can go through all those bug fixes projects if necessary to check to see if the bug remains fixed.

So - it's similar to "unit tests" but not so formal. Might be useful approach for others in a similar situation. I haven't actually tried unit testing myself - so don't know enough to make a proper comparison - but this works well enough for me.

AUTOMATION OF FREQUENTLY USED CODE FRAGMENTS


Another thing is to do with the architecture of the program. If you have something you do frequently - can you automate it and simplify the coding?

In my programs - I have lots of user set variables in the interface.

Take for example a check box

When user checks the box - then in my programs at least:

  • the code has to respond to user clicks on the check box and change state internally
  • be ready to display it with the correct check state whenever the window is shown
  • save the check state to a project if the user saves all their settings as a project
  • Read the check state from a saved project when user opens it
  • You might also sometimes want to record it as an "undo state" for multiple undo
  • Have a record of the default state of that check box so that if you do a reset then it resets to its default
  • Have a record of which windows the check box appears in (this is because my programs permit "per window" resets).
If I add an edit box with a spin control to adjust the number, there are several other things that need to be done as well.

So - that's potentially a lot of things to go wrong with  simple check box. For instance user might switch it on - but when you exit the program and start it up again - it forgets its previous state because of some typO In the code to save it to the project or .ini file.

So - it's a huge saving in a big project - if you can simplify this. And the code is highly repetitive - and - there are only a few things that change in that code from one check box to the next. So - why have to rewrite the same thing over and over - same boilerplate code?

The only original thing each time is - the id for the control, the string used to identify the variable in the .ini  file or project, the window handles for the windows it appears in - and - whatever it is you use to store the check state internally in your program.

In Lissajous 3D - then I do just about all of this in a single line of code. I don't even have to add a check box handler case when I add the new check box to the UI - this is taken care of automatically, just make sure that I include the check box id in that line of code.

In my main program Bounce Metronome - then I need - about three or four lines of code to add a new check box + click / drag ui editing to add it to the window - and that does all of this automatically.

The way I do it is - first - a subroutine that does most of that work - and also - my own pre-processor that goes through the program and adds extra "boiler plate" code to it derived from that single line of code.

It's not only faster to write - it also completely eliminates a whole class of bugs so that they never occur in my program.

I do still get bugs with my checkboxes - but - if it fails - it fails in a very obvious way (which you can miss while testing).

So for instance - if I find that I can successfully turn the check box on and off in the user interface - I know automatically that it is also saving to .ini files correctly - and all those other things that I have tied together in this small bit of code.

Generally - any time you find yourself writing almost identical code at least three times, chances are you can find a way of improving your program and making it more bug free by writing it a different way.

If you just write the almost identical code twice - and if not too long - then it might not be worth the effort of doing this. But by the time you get to the third or fourth time - depending on the context, you can think seriously about whether there is a better way of doing it, and if your program has hundreds of instances of almost identical code blocks, then most likely you can make your programming a lot faster, and less error prone - by spending a few hours or days even working out something like this.

Of course when you do that sort of thing, especially if it is old code or not written by you - it is important to check to be sure that the code really is identical before you collapse it all into a single routine or single uniform way of doing things (if necessary do a diff to be sure),

DON'T BE TOO CLEVER!


This is perhaps one of the most important ones. Often you have the choice of writing an ingenious bit of coding that shows your prowess as a programmer and your understanding of advanced technical concepts - and another way of doing it that is more pedestrian perhaps - but easier to read.

It's almost never worth doing the clever solution. You only need to do that if you are doing highly opimized code.

For instance - if you are working on a new algorithm to slightly speed up Fast Fourier Transforms - where doubling the speed of your code is a major breakthrough and increasing it by 10% might be an achievement - of course you will be doing lots of clever coding tricks, is unavoidable, and will write a program maybe of 1000 lines or 10,000 lines full of dazzlingly complex and intricate code - when a simpler approach would be say a hundred lines.

In that situation yes it is worth doing.

But it is rare indeed to meet a situation like that in modern programming. Aim for readability.

Otherwise you can introduce unforeseen bugs, and the code is far harder to read.

A classic example is the XOR swap algorithm

It is impossible to read if you don't understand the trick. And - it may save some assembly language instructions in theory - but in practice the compiler will optimize them out anyway, you can almost never improve code with these sorts of tricks, and the performance gains are so minimal anyway in most situations that you can't measure them.

It is several decades now since the time when optimizations like that were worth doing in any high level language.

And this particular example has a major bug that if you try to swap a variable with itself (i.e. same memory location, not identical value), it sets it to zero.

It's use in a higher level language will almost always be a sign that some programmer just wants to prove how clever he or she is, and will be a maintenance disaster and source for bugs. Yes you can fix the bug by adding in a test to see if the two variables have the same address before you do the xor - but - why make things so complex for yourself in the first place? And what's more, on modern CPUs, XOR can be slower than user of a temporary variable because of the way it forces the CPU to work in sequential order rather than parallel pipelines.

Well - that's an obvious example - but how often have you found yourself using some neat coding trick you read about, just because it's neat and fun even though it's not at all necessary for the job at hand?

That's okay for an obfuscated c program, or for a coding competition - but not for production code. It makes it harder to maintain, to debug, and some of the coding tricks may have unforeseen buggy side effects, like the XOR trick.

Now that depends on the programmer. So for instance, happens that I find the ?: notation of c programming easy to read, over several decades of frequent use of the notation, so often have complex statements like this in my code:

x=
a
 ?b
  ?c?d:e
  :f
:g?h:i;

For me that lets me express something in a compact and easy to read way that would otherwise require many lines of code.

But for others it would be an unreadable piece of obfuscated code.

So - you have to make a judgement call on this. But the main thing is - that your code has to be as easy to read as possible - by yourself or by others - and it is almost never worth prioritizing anything else above readability.

SYNTAX COLOURING AND FORMATTING


More of a beginner's tip this - but if you haven't got used to it yet - then syntax colouring is tremendously helpful for avoiding many bugs that can slip through the net of a compiler.

Also - consistent formatting.

Myself, I use the convention of matching braces like this in c-code

if(..)
{
 for(....)
 {
 }
}

where the braces align with each other vertically. In my compiler I can use Ctrl + } to move to the matching brace - then I check the column number - and if it is indented by the same amount - I know I've got the braces nested correctly. Again depends on the style of programming of course - but I can't even begin to count how many bugs in my code this habit has prevented before they had a chance to occur.

If there are many lines in between I add comments to make clear which brace matches with which, as in

for(i=0;i<10;i++)
{
...

} // i

There the // i is a comment to remind me that this is the end brace for the i for loop.

You'll develop your own habits of course, depending on the language, coding style, type of program, and context.

So - not suggesting anything particular. Just to pay attention to the way you format your code - and be consistent - and develop good habits - and this can prevent a wide range of different bugs from ever getting into your code.

About the Author

Robert Walker

Robert Walker

Writer of articles on Mars and Space issues - Software Developer of Tune Smithy, Bounce Metronome etc.
Studied at Wolfson College, Oxford
Lives in Isle of Mull
4.8m answer views110.4k this month
Top Writer2017, 2016, and 2015
Published WriterHuffPost, Slate, and 4 more