Approach to developing games

Started by
19 comments, last by bootstrap 17 years ago
Hello I just wanted to share some of my thoughts about game development. I have been programming for almost 7 years. I started programming in C where the approach was very hands-on. Then I started to learn OO programming and my approach was to find general solutions to my often very fuzzy goals (e.g. write a cross-platform 3d engine so I can make a super mmorpg that does everything). I started to see my productivity sink and I spent much time writing code for imaginary problems. I kept doing the same thing because I thought it was the right way to do things. I thought: I probably need feature X sometime so I prepare my self and code it now. Later I've realised that it resulted in lots of wasted energy because of unused code. Later I started to use a new approach where I looked for more specific problems to solve. Instead of searching for problems to solve I simply took care of the ones that were at hand, i.e. I need feature X right now so I write code for it. My productivity increased drasticly. Problem was that I still tried to find general solutions to my problems. E.g. if I needed to render a 3d model I wrote a model loader, renderer, render-list, event system, transform hierarchy, camera, resource manager, scene manager, effect system, etc. etc. Now I'm starting to think if I find an even better approach. I'm starting to wonder if the best approach is to be hands-on, find specific problems and write a specific solution to that problem. If I later find that my solution need to be more general I simply rewrite it. The conventional wizdom says that this approach will result in spagetti code with lots of bugs. I'm not sure this is true. I've always assumed it to be true because it sounds true but now there is an entire development process that involves frequently changing the design and rewriting the code (agile/evolutionary programming). Anyway, I wonder if people here have any experience in being more hands-on and not trying to find general solutions to problems. Are you productive?

www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity

Advertisement
I use a pencil and paper. If you're just sitting down and hacking this stuff out, you're going to end up with what I like to call "OO spaghetti code," which is to procedural spaghetti code what polonium is to rat poison.
http://www.refactoring.com/
Quote:Original post by Opwiz
If I later find that my solution need to be more general I simply rewrite it. The conventional wizdom says that this approach will result in spagetti code with lots of bugs. I'm not sure this is true. I've always assumed it to be true because it sounds true but now there is an entire development process that involves frequently changing the design and rewriting the code (agile/evolutionary programming). Anyway, I wonder if people here have any experience in being more hands-on and not trying to find general solutions to problems. Are you productive?


I have always worked in an experimental and specific fashion, refactoring code to make it more general when needed, and only when needed. However, it still pays to learn the overall structural stuff, so that you can anticipate how things may need change if they ever do so.

The worst code I read is actually the stuff that is written for the general case - usually so general that it's 90% flexibility scaffolding and only 10% semantic content.

Some of my core development tenets: "YAGNI", "Refactor Mercilessly", "Once, Twice, Refactor", "Zero, One, Infinity". In addition to this, I usually unit-test my modules (and force myself to make the modules unit-testable by writing the tests before the modules).

I keep together a module graph (on paper) which I regularly update from the code, and I have developed two interesting tricks to detect places that need refactoring from that graph.

The code evolves in write-refactor cycles: I write new functionality using existing one, test it, then refactor the involved code areas (testing them along the way) until the "Once, Twice, Refactor" consideration is done. Then, I update the module graph, identify places which need refactoring, and repeat the refactor-and-test loop again until the graph is clean. One last full system build and test later, I commit to my source control, and repeat the process.

The key word here is functionality. I only write code which affects the resulting object. That is, it should be able to display or compute something new in the hands of an user (as opposed to the hands of a programmer), which also includes performance increases. The rule here is simple: if a non-technical end user cannot see the difference between the program before the feature, and the program after the feature, then it's not worth adding.
I would add the probably-obvious caveat that you should, to the best of your ability, determine as much of the requirements before hand as possible. Basically, this amounts to where you set the bar for "immediate need" or the granularity with which you apply your solution. As others have said, it's equally important to anticipate possible changes in your needs as well; just to avoid painting yourself into a corner.

Its also true that these changes will sometimes cascade into other parts of your program. This may make you *feel* more efficient because you're spending a lot of time doing and less time thinking. Ideally, you simply want to be spending less time. Period. If spending 15 minutes thinking saves an hour of doing, then thats the more efficient route.

Say, for example, that in the course of writing your game you decide that you need a vector class. You only need to be able to add and multiply vectors right now. Is it more efficient to write just the functionality you need now, adding additional functions as you discover a need for them (adding a mental context switch,) or would it be easier to write a vector class with all the basic functionality up front? If you anticipate needing more functionality in the future, I would argue that the latter is more efficient in the long run.

Ultimately, good practices are not about swinging from one extreme to the other, or subscribing to the development buzzword de jure, its about finding the balance that works for you.

throw table_exception("(? ???)? ? ???");

Quote:Original post by ravyne2001
Say, for example, that in the course of writing your game you decide that you need a vector class. You only need to be able to add and multiply vectors right now. Is it more efficient to write just the functionality you need now, adding additional functions as you discover a need for them (adding a mental context switch,) or would it be easier to write a vector class with all the basic functionality up front? If you anticipate needing more functionality in the future, I would argue that the latter is more efficient in the long run.

There was/is a great comment on the c2 wiki about this kind of thinking, unfortunately I can't find it right now, so I'll paraphrase as much as I can.

It's going to take the same time to write the methods now as it is in two weeks, or two months, when you finally get round to needing them. You could spend half an hour now, or half an hour in a few weeks time, or you could end up never needing it - in which case you obviously gain from defering the work until later.

The rebuttal is of course "but I know how to do this now". So you're telling me this code is so complicated, that even you won't be able to understand it in a few months time? In that case you're screwed either way.

The whole idea that you can avoid a "mental concept switch" by doing more work now when you don't need to is misplaced and IMHO just leads to over-engineered and over-complicated code.
Quote:Original post by OrangyTang
It's going to take the same time to write the methods now as it is in two weeks, or two months, when you finally get round to needing them. You could spend half an hour now, or half an hour in a few weeks time, or you could end up never needing it - in which case you obviously gain from defering the work until later.

What if, unknown to you, adding that extra functionality later will require modifying other parts of the code you haven't written yet? You could spend half an hour now, or two hours in a few weeks time.

If you're working in a team, it's also possible that, a few weeks later, some other members of your team won't be able to continue development until a particular feature is implemented. Half-an-hour of potentially wasted time for one person has become half-an-hour of definitely wasted time for one or more members of your team.

Deferring work until the last possible minute is rarely the best solution outside programming. Deciding when to write a piece of code should be a balancing act between the cost of writing code that isn't needed, and the cost of deferring it until it really is needed.

Black-and-white "don't write any code you don't need right away" advice, like most black-and-white advice, is usually wrong.
Quote:Original post by Nathan Baum
Deferring work until the last possible minute is rarely the best solution outside programming. Deciding when to write a piece of code should be a balancing act between the cost of writing code that isn't needed, and the cost of deferring it until it really is needed.

Black-and-white "don't write any code you don't need right away" advice, like most black-and-white advice, is usually wrong.

Oh I agree, but I'm not suggesting doing everything as late as possible, but rather that ravyne2001's suggestion of doing everything as early as possible isn't always a good idea.
Quote:Original post by OrangyTang
Quote:Original post by Nathan Baum
Deferring work until the last possible minute is rarely the best solution outside programming. Deciding when to write a piece of code should be a balancing act between the cost of writing code that isn't needed, and the cost of deferring it until it really is needed.

Black-and-white "don't write any code you don't need right away" advice, like most black-and-white advice, is usually wrong.

Oh I agree, but I'm not suggesting doing everything as late as possible, but rather that ravyne2001's suggestion of doing everything as early as possible isn't always a good idea.

ravyne2001 didn't actually suggest that. What was said was "if you anticipate needing more functionality in the future" it'll probably be faster in the long run to add it now. Of course it will take experience for your anticipations to match up with reality. In the specific example, though, it is probably reasonable to anticipate that the vector will eventually need a dot product operation, say, even though you don't need it now.

This topic is closed to new replies.

Advertisement