Jump to content
  • Advertisement
Sign in to follow this  
Kwame Anim-Addo

Advice for writing good code

This topic is 557 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The thing that scares me most is the the aspect of indie game development is providing support for code bugs after releasing a game. I see games that have a boatload of bugs reported on Steam. I'm not willing to put myself in that position.

That got me thinking that the best way to minimize the amount of bugs created would be to: 

1. Write code that's less likely to break. 

2. Bring in as many play testers as possible to before the release.

I would also need to have a method to efficiently identify the cause of bugs.

I have the following questions:

What books can the community recommend for writing efficient code that minimizes potential bugs?  There's a well reviewed one on Amazon, but it's 900 pages. 'Clean Code' was printed poorly according to multiple reviews, so I'm not interested in that one either. 

Are there any tools or techniques the development studios use to identify the cause of bugs efficiently?

The book Game Programming Patters explained the Command pattern can be used to re-play a game. Would this be feasible to implement in a shipped game by recording commands executed after a save in order to identify the source of potential defects?  

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

Are there any tools or techniques the development studios use to identify the cause of bugs efficiently?


Things you NEED to know:
- All of the features of your debugger.
- All of the features of your profiler.
- Everything related to unit testing.
- Everything related to integration testing.

Programming guidelines:
- Do the simplest thing that could possibly work.
- Don't write code that you aren't going to use NOW.
- Delete code which is not being used.
- Delete code which is not covered by a unit test.
- If you KNOW something will perform terribly, optimize it now. Otherwise, profile it later.
- Keep variables as short-lived (or encapsulated) as possible (locals > parameters > closures > private members >>>> public members >>>>>> thread statics >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> globals)
- Keep variables in valid states at all times (don't leave things null, set them to invalid values, or use types which even allow invalid values in the first place).
- Avoid keeping variables which mean the same thing in multiple places.
- Use immutable variables until you're *sure* you need mutable ones.
- Make constants for your magic numbers now, not later.
- Keep your functions as short as possible. If you find yourself writing a big function, split it up.
- Avoid inheritance until you are absolutely sure you need it.
- Prefer simple functions and functional style over classes. Don't use classes until you need them.
- When you have classes, ensure that their instances are always in a valid state.
- Refactor frequently, and use unit tests to catch refactoring mistakes.
- Don't use threads until you ABSOLUTELY know what you're doing.
- Never use linked lists.
- Never concatenate strings using the + operator in .NET. Edited by Nypyren

Share this post


Link to post
Share on other sites

 

Are there any tools or techniques the development studios use to identify the cause of bugs efficiently?


Things you NEED to know:
- All of the features of your debugger.
- All of the features of your profiler.
- Everything related to unit testing.
- Everything related to integration testing.

Programming guidelines:
- Do the simplest thing that could possibly work.
- Don't write code that you aren't going to use NOW.
- Delete code which is not being used.
- Delete code which is not covered by a unit test.
- If you KNOW something will perform terribly, optimize it now. Otherwise, profile it later.
- Keep variables as short-lived (or encapsulated) as possible (locals > parameters > closures > private members >>>> public members >>>>>> thread statics >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> globals)
- Keep variables in valid states at all times (don't leave things null, set them to invalid values, or use types which even allow invalid values in the first place).
- Avoid keeping variables which mean the same thing in multiple places.
- Use immutable variables until you're *sure* you need mutable ones.
- Make constants for your magic numbers now, not later.
- Keep your functions as short as possible. If you find yourself writing a big function, split it up.
- Avoid inheritance until you are absolutely sure you need it.
- Prefer simple functions and functional style over classes. Don't use classes until you need them.
- When you have classes, ensure that their instances are always in a valid state.
- Refactor frequently, and use unit tests to catch refactoring mistakes.
- Don't use threads until you ABSOLUTELY know what you're doing.
- Never use linked lists.
- Never concatenate strings using the + operator in .NET.

 

Some of these are fantastic, especially magic numbers, it's so easy to make a rectangle draw at 32,32 but if you ever change that, Going through all the code is a ballache.

 

However can you explain the last one? Not sure why that would  be an issue.

Share this post


Link to post
Share on other sites
However can you explain the last one? Not sure why that would  be an issue.

Strings are immutable reference types. Concatenating strings with the + operator creates an entirely new string, and then copies the content of the two operand strings into it. This is somewhat less fast than other methods of building up a string dynamically, and it also produces significantly more garbage objects that are short-lived and thus more likely to force a gen0 collection (which thus pushes all the uncollectable gen0 stuff into gen1, increasing its size, and thus increase the cost of a gen1 collection. Et cetera for gen2.

"Never" using operator+ for strings is harsh -- it's probably okay to do it once or twice in parts of the code that aren't anywhere near the time-sensitive inner loops. But, on the other hand, "never" helps establish the habit of using other string formatting mechanisms which don't have quite the same probems (or avoiding string formatting altogether). And it's not like the alternative mechanisms are really tedious, so it's certainly a reasonable habit to develop.

Outside of the performance and technical issues, concatenation of strings that will be displayed (and thus localized) makes that text harder (or impossible) to localize correctly. The component strings lose their context, which is important for other languages (some languages have gendered words, for example), and the use of the + enforces an order which is not universal for all languages.

Edited by Josh Petrie

Share this post


Link to post
Share on other sites

However can you explain the last one? Not sure why that would  be an issue.

Strings are immutable reference types. Concatenating strings with the + operator creates an entirely new string, and then copies the content of the two operand strings into it. This is somewhat less fast than other methods of building up a string dynamically, and it also produces significantly more garbage objects that are short-lived and thus more likely to force a gen0 collection (which thus pushes all the uncollectable gen0 stuff into gen1, increasing its size, and thus increase the cost of a gen1 collection. Et cetera for gen2.
"Never" using operator+ for strings is harsh -- it's probably okay to do it once or twice in parts of the code that aren't anywhere near the time-sensitive inner loops. But, on the other hand, "never" helps establish the habit of using other string formatting mechanisms which don't have quite the same probems (or avoiding string formatting altogether). And it's not like the alternative mechanisms are really tedious, so it's certainly a reasonable habit to develop.


Yes, exactly. It's an exaggeration meant to be a reminder about the dangers of certain, seemingly trivial operations. Using + is fine if you're gluing together a few small strings (like for a debug message or a ("Lives: "+numLives) expression for your HUD).

A few weeks ago I was investigating some slow C# code and found that a roughly 100,000 character string was being built one character at a time using a "string += char" expression in a loop.

I ended up calculating that the amount of memory access performed just for concatenations was somewhere in the ballpark of 20 gigabytes of reads/writes. And that's just for the string data. Obviously the garbage collector had to clean up all those temporary strings, and who KNOWS how much overhead was incurred from that.

The entire operation took ~6 seconds. In a game, 6 seconds is an unacceptably long amount of time to wait for anything. And hell, even in command line tools that you normally expect to take a while, there's no excuse to write code that slow. Changing to a StringBuilder used far less memory accesses, was unnoticable (i.e. EXTREMELY fast), and did not trigger the garbage collector. Edited by Nypyren

Share this post


Link to post
Share on other sites

If you do not like fixing bugs, then I am afraid that software development is not for you. In any sort of software development, a majority of your time will be spent fixing bugs. Some will be easy to find; others difficult; some easy to fix, others difficult.

Fixing bugs in my project can take anything from about 2 minutes to 4 months per bug. Subtler bugs can lay dormant undiscovered for years until somebody does a very specific combination of things that even the best testers could not imagine.

Writing good code can certainly greatly reduce the number of bugs (and make them easier to find when they do exist), but you will never be able to eliminate them entirely. Nypyren has given some useful tips: another is to make your code as modular as possible so that it is easy to track down and fix a bug in a specific part of the code (which I think is what a lot of Nypyren's advice amounts to in any event).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!