It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.

by Peter Warden
Gamasutra
[Author's Bio]
January 19, 2001

The Importance of Naming

Over-general Designs

Printer Friendly Version
 
Discuss this Article

 

 

Letters to the Editor:
Write a letter
View all letters


Features

What Your Mother Never Told You
about Game Programming

Over-general Designs

In game programming, you almost never get handed a complete set of requirements. One way of dealing with this is to attempt to write a very general system that will cope with a very wide range of needs. Though lecturers are very fond of such top-down, abstract systems as examples, I've found that the design of the system has to be aware of the specifics of how it will be used, or the code that relies on it ends up working around the system rather than being helped by it. The heart of the problem is that there's always a choice of which abstractions best model the problem, and until you know the problem well, picking the right abstractions is impossible.

With input, picking an abstraction that encompasses joypads, mice, joysticks, and keyboards -- and isn't awkward to use -- is not something I've ever succeeded at. Even though they belong to a family of devices with similar purposes, finding a useful subset of properties that they have in common is very hard.

The way I've found around such problems is to tackle the problem from the other end and work through some examples of how I think the system is likely to be used. This focuses my mind on what the common cases will be; since they're the most important, I can make sure the design concentrates on those. It's a lot easier to spot potential problems at an early stage, rather than realizing them after it's all been implemented, causing you to have to corrupt the abstract design by hacking in workarounds.

Take the case of input. I might see two main needs, one for pretty undemanding tasks such as menu control, the other for things such as control of the main character where all the information you can get from the control device is essential. In the first case, a simple abstract system that posted events to interested parties when a major input change happened would probably do everything that was needed. For the latter, I'd expose the full interface to the device with minimal wrapping, and let the calling code pull out the information it wanted. Trying to cope with the radically different needs of the client code within the same system would mean both would be served poorly.

Listings 3.1 and 3.2 take a look at how to design the interface to a graphics module, and how tricky it can be to try to make it general.

"Keep It Simple, Stupid!"

The real competition in games these days is no longer in the graphical technology, but in the content. To give the artists and designers as much time as possible to get all that great content in, we need to get a version of the game they can use very early on in the project. This kind of rapid development isn't common in games; in the past the priority has been on writing extremely efficient code, with the time taken to write it not as important. Now the emphasis is increasingly on getting something working at all, and then worrying about efficiency where it's important. This doesn't mean you can be careless writing code, of course, just that the varying times that different ways of coding something would take are now much more important than in the past. It's hard to adjust to writing very naïve code where needed when every instinct is to always have efficiency as your highest priority.

Premature Optimization Is the Root of All Evil
Compared to writing code that works, optimizing working code is straightforward. It's also often a lot more fun! The problem is that debugging, maintaining, or re-optimizing code that's already been optimized is far harder than doing the same with clearer code. This may sound academic, but in practice the code that's optimized early on is seldom the code that takes up most of the execution time, since programmers are notoriously bad at guessing the bottlenecks in the code. Time that could be spent optimizing the really important code is instead wasted on fixing code that would take almost none of the execution time, even if it was written to be easily understood rather than to be fast. Profiling is absolutely vital. You'll often find that 90 percent of the time is spent in 5 percent of the code, and so the gains you make from optimizing that section are far bigger than any other code. Knowing how to optimize is a vital skill, but knowing when not to do it can be just as important.

Lying Comments
When I first started writing commercial game code, my code was liberally littered with comments, and I couldn't imagine any drawbacks to this. As time passed, I noticed something odd: the code and the comments grew increasingly out of sync, and I found that wrong comments cost me more time than correct comments saved me. The cutting and pasting, and late night alterations that happen when the pressure's on all meant that the code changed while the comments didn't.

I find code in which code and comments seem to clash very difficult to sort out, largely because the comments have to be chased up just in case they're true, even if they seem obviously wrong. The problem is that there's no natural reason for the comments and code to stay connected, and in the heat of development the time needed to maintain the comments is seldom available. To minimize the problem, my style is now to have a bare minimum of comments but to have my code very verbose, with all steps of the algorithms laid out in simple steps and with clear names for everything throughout. I reserve comments for areas where I'm doing something that's unusual or obscure, in the hope that their scarcity will make them stand out, and thus be less likely to be forgotten when the code changes. Obviously there are exceptions to this, such as in assembler where the language doesn't give you the chance to be verbose, and so comments are essential; you just have to bite the bullet and spend time maintaining them.

Conclusion

I've tried to apply the optimization mantra to my coding process and look at what problems consume most of my coding time. They are pretty mundane, even obvious, but if I can save even a little time by focusing on them, it'll mean we can get the game out faster. I know this is a bit of a pipe dream, but have you ever thought how nice it would be to actually implement something from the "if we have time" wish list?

As long as I'm bugged by how much cooler the games I've worked on could have been if we'd only had a little more time, I'll keep trying to figure out how to improve my coding.

Resources

Web Sites

http://www.refactoring.com has lots more ideas on how to rescue code that's in trouble.

http://www.extremeprogramming.org details an interesting approach to software design that's refreshingly grounded in practice. Will give you lots of ideas you can try adding to your current process.

http://www.muckyfoot.com/downloads/tom.shtml has an excellent presentation from the Windows Game Developer Conference that takes a level-headed look at the emerging technology of subdivision surfaces and how they can actually be used to improve games.

http://mindprod.com/unmain.html is both a very funny and a very scary guide to writing unmaintainable code

Books

Gamma, Erich, and others. Design Patterns. Reading, Mass.: Addison-Wesley, 1995 (ISBN 0201633612).

Lakos, John S. Large-scale C++ Software Design. Reading, Mass.: Addison-Wesley, 1996 (ISBN 0201633620).

McConnell, Steve C. Code Complete: A Practical Handbook of Software Construction. Redmond, Wash.: Microsoft Press, 1993 (ISBN 1556154844).

McConnell, Steve C. Rapid Development: Taming Wild Software Schedules. Redmond, Wash.: Microsoft Press, 1996 (ISBN 1556159005).

McConnell, Steve C. Software Project Survival Guide. Redmond, Wash.: Microsoft Press, 1997 (ISBN 1572316217).

McConnell, Steve C. After the Gold Rush: Creating a True Profession of Software Engineering. Redmond, Wash.: Microsoft Press, 1997 (ISBN 0735608776).

Meyers, Scott. More Effective C++: 35 New Ways to Improve Your Programs and Designs. Reading, Mass.: Addison-Wesley, 1995 (ISBN: 020163371X).

Sutter, Herb. Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions. Reading, Mass.: Addison-Wesley, 1999 (ISBN: 0201615622).

Discuss this article in Gamasutra's discussion forums

________________________________________________________

[Back to] The Importance of Naming

 


join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2003 CMP Media LLC

privacy policy
| terms of service