How to avoid bugs

Started by
24 comments, last by Anri 5 years, 7 months ago
  • Use the debugger.
  • Enable debug mode on the API where applicable (i.e. DirectX).
  • Address all compiler warning messages.
  • Enable leak detection.
  • Think out of the box (i.e. How can a user break my program. What happens if the enter text in a number field?).
  • Test hard and test often.

There are many many more. Even many that I admit I don't know exist.

I have been coding in C++ since 2005, so that would put me somewhere in the beginner to intermediate level.

Advertisement

You avoid bugs (in the future) by writing bugs (in the past).

If you ever meet a programmer who tells you they've never had a bug, they're lying. Like anything, you learn by doing, and mistakes (bugs, poor design decisions, using the wrong tool for the job) are all valuable learning experiences.

That's not to say you shouldn't use all the valuable ideas expressed in this thread, but worrying about bugs should be the least important thing in your mind right now.

Besides, sometimes a bug really is a feature. Look at rocket jumping or strafe jumping... those were initially bugs in Quake and entire games have since been built around them.

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
4 hours ago, ChaosEngine said:

If you ever meet a programmer who tells you they've never had a bug, they're lying. Like anything, you learn by doing, and mistakes (bugs, poor design decisions, using the wrong tool for the job) are all valuable learning experiences.

100% this. There isn't a programmer out there who hasn't had bugs in his/her software.

I don't work in the games industry, but I do work in software and have worked in a variety of different aspects of the industry over the past few years (long story how). Another thing worth noting is that beyond a point bugs are an unavoidable side effect of coding. There's ways to mitigate its effects and to deal with it, but usually there will be bugs throughout the software lifecycle. There's just too many ways that things can break, usually beyond the realm of predictability. After a point, there's only so much we can foresee of potential edge cases and usage cases of the software. Typically the key is to be able to mitigate, diagnose, and fix quickly.

That's not to say that we want bugs: we avoid as much as we can by means of unit testing, performance testing, and CI/CD pipelines to mitigate these issues, along with all the tools others have already posted about.

No one expects the Spanish Inquisition!

There is no clean answer. Just expirience and muscular memory

 

I find the best way to prevent bugs is to write code that's easy to understand. Do what you can to make your intentions obvious through your code. Whatever you can't make obvious document via comments. Short term this helps prevent bugs since you can "gut check" your code to see if it's doing the right thing more easily. In team situations it makes the code easier to review as well.

Most bugs IME are due to simple oversights when writing up code. The harder you have to work to "get" the code the more likely you are to miss a detail which leads to a bug.

Longer term when you go back to revisit old code simple code helps even more. The more easily you can figure out what you were trying to do the less likely you are to add new bugs or bring back old bugs.

A few suggestions

  • Code small features one at a time, don't do too much at once.
  • Work out how you want your small feature to work before you write it.
  • Source control gives you a nice way to undo your changes and start over if you're completely stumped.
  • Keep your functions short with few arguments.
  • Keep your functions independent of each other whenever possible. Functions calling each other is fine but having something like prepareFoo then doFoo is more likely to lead to bugs since you could forget to call prepareFoo or make other mistakes.
  • Avoid having widely shared data that can be modified in many places (e.g. global variables, singletons etc.)
  • Avoid duplication of code. Fixing a bug once is enough work. Fixing lots of the same bug is an exercise in frustration.
  • Fail hard and loud on unacceptable program data. The quicker a bug leads to a catastrophic event the easier it is to find and fix. This is what can go wrong if you don't throw up huge error messages or outright crash on bad input: https://arstechnica.com/gaming/2018/07/a-years-old-one-letter-typo-led-to-aliens-colonial-marines-awful-ai/

As other posters have said, you will get bugs still, but simpler code should make them easier to find and fix.

--------------------------Insert witty comment here!--------------------------

The best way to avoid bugs is to look in the damn code of the game (or whatever you program.).They hide there.

On 8/13/2018 at 9:05 PM, Timothy Sharp said:

or atleast the beginning I just need to learn how to program

you just need to study high math and other related math-based areas for 5 years fulltime. calculus and linear algebra is just a preparation for studing math related to programming. After 5 years university course you will be ready to start study game development.  Anybody who says that programmers can be trained faster just lie. Programming language is just a pen intended to describe how to solve mathematical tasks to computer. So it imposible to programm without understanding background math. Also it is will help with bugs. Most bugs comes from misunderstanding or not enought understending of task. So only tool to avoid bugs is improve undestending of mathematical background.

#define if(a) if((a) && rand()%100)

Time ago I followed some advices about doing a resource manager, after debating a lot and seeing my rates going down, somebody, who was at rockstar level, proposed to use some code of his. At first glance it was great and solved the problem with a relatively elegant solution. I adopted the code ( i admit i copy and pasted it ) and it worked flawlessly for the most of the times. Once, suddenly strange problems appeared during the runtime phase , objects pointed to wrong meshes and everytime i reran the program i got different behaviour, turned out the the buggy code was the resource manager itself that I copy and pasted from here. So i rewrote the code by myself and i didn't experience those stange bugs anymore ( some blocks of memory weren't properly release and remained 'active' even after the program session was closed ). The moral is never copy and paste into serious programming, it is good to learn, but you and only you can solve your problems, and like someone much more experienced than me once wrote, your best debugging tool is your brain, for me it was a lesson learned.

In my opinion so far, make a code that is easy to understand, it will save yourself and others when the code gets bigger. Make enough informative comments to make sure you remember what you did so you (and others) know what it does. Bugs will be there, but nothing better than codes that everyone can understand to solve those bugs quickly.

Secondly, always think ahead of what you write. If you put ++power for a character, think like, when should it be called? how does it added? does the owner of that variable already removed? is it called during attack animation callback? is there a network request failure that should cancel out ++power? etc. This usually comes with experience because you got to make something first to understand what you need and what's going on with your program.

Then to make things easier, always test your code. Program yourself some unit testing (and any other kind of testing methods out there) to convince yourself with the code. In easy term, it's basically like a checklist before going on a trip. You'll face trouble on your trip if you're missing something no matter how small it is as long as it matters right? So you got to always do a proper checking on all items you have before going on a trip. ?

One thing I learned along the way is to always initialize member variables in your classes to some default value (0, nullptr, etc.). Sure, It may slow down your object generation code, but it is ultimately the best way to ensure gdb will catch an error if using a pointer that isn't meant to be nullptr, or a variable that isn't supposed to be just any random number the program decides (If max health is 100, you don't want it to be 5937295 at initialization).

Not initializing variables is the number 1 cause of Heisenbugs imo.

View my game dev blog here!

This topic is closed to new replies.

Advertisement