Some Thoughts on Software Design

Published January 10, 2012
Advertisement
Software Engineering as I understand it involves the concept of software design. Anyone can program, and I would even venture to say that programming is the easy part. Good software design is where things get hairy. I consider myself a seasoned programmer, but a somewhat fledgling Software Engineer--a state that I think is fairly commonplace among academic or hobbyist developers. Bad habits done out ignorance can carry over into the industry and wreak havoc on bigger projects. I too am struggling when it comes to designing and implementing larger systems (like a game engine), although I am learning a lot. Though I am still inexperienced, I thought I might share some of my realizations so far. If you consider yourself a seasoned software engineer, feel free to comment/correct as you see fit.

[font=georgia,serif]

Formulate Requirements

[/font]

First of all, trying to design a system without knowing the requirements will drive you insane if you are expecting any semblance of quality in your architecture. I know this because I've tried. My previous attempt at creating a game engine went down in flaming glory because the end result wasn't as flexible and usable as I had hoped. Before you write a single line of code, I implore you, write a design document for your project. Describe what the system needs to do in detail. Why is this so important? Without this step, you're essentially flying blind. You will re-factor your code three times as often, bloat your code base including features you don't need; and if you're like me, you'll agonize over finding the Right Way to do it--except you won't, because you don't know what you need.

Case in point: in my first engine, I rewrote my resource manager four times. Not a simple re-factor mind you; a complete rewrite. I included features like loading from a separate thread, which is a great feature, except that I didn't really need it. I just thought it was cool and that every engine should use it. Granted, I learned a lot about what I did need during those four rewrites, but I would have been better off starting with the essentials and refactoring from there. I went into it without fleshing out how the end product would use the system; as a result, my design suffered from code bloat.

[font=georgia,serif]

Build a (Good) Foundation

[/font]

I've heard differing opinions on this, so take it with a grain of salt. I see a two specific mistakes that neophyte developers make (including myself) when they are just starting a big project. Either they try to sketch out the entire system (a large one, mind you) on paper, in detail, including every major class and how they'll interact with other classes; or they don't attempt to design anything and just start coding. The latter is just pure laziness in my opinion--the chances of designing a good system with that strategy are akin to winning the lottery (unless you're John Carmack). The former, however, is just as destructive. From my experience, trying to build exclusive from the top down is paralyzing. You scrap design after design trying to find the perfect one (hint: it doesn't exist).

As with all things in life, good design comes with moderation. Begin with your requirements and write some hypothetical sample code of how you will use the system. One good way I've found is to write a bogus program (or part of one) in pseudo code, testing out various interfaces and ideas. At the same time, begin building the foundation for your system. If it's a game, start with the basics, like a basic map loader. Just get something working.

[font=georgia,serif]Break Down Work into Manageable Chunks[/font]



As you build the components of your system, not only will the next step become more clear, but so will the requirements. You'll realize something you need but couldn't have known early on in the process. This allows you to refine your requirements as well as your code. By starting simple, you will save time refactoring and gain momentum and efficiency. I see many developers who attempt to write hundreds of lines of code without ever compiling it. They proceed to spend hours trying to get it to even compile, and then twice as many working out the bugs. This is not good practice; a better method is to utilize unit testing. This is the process of writing small chunks of code and then rigorously testing it before moving on to another component. This gives you confidence in the components of your system as you build on them, and boosts your morale as you see small parts working independently. Furthermore, it simplifies bug fixing since you can focus on one part of the system exclusively.

[font=georgia,serif]Pick an Achievable Goal and Stick to It[/font]



This is probably the most important point. Avoid the pain and suffering of trying to design the perfect system for any product. It won't happen. Always know your requirements and design for that only. This is especially true if you are trying something new. I don't personally know how the guys at Epic designed Unreal 3 or their story, but I would imagine they built it up using the good parts of their games. Not only that, but the guys developing Unreal Engine 4 are probably the same ones who built the previous three engines (at least the lead developers). In short, defer your amazing do-it-all project for when you actually know what you're doing (I say this to myself as well). Most of us started out wanting to develop the best MMO on the planet; we quickly realized this was foolish. However, some of us are repeating that foolishness on a smaller scale. We're trying to build something we have little experience with, and make it better than everything else out there. That's just my opinion.

How does this apply to me? Well, a lot. I'm trying to trim down my grandiose plans to something manageable. For instance, what are my goals? I've spoken about those in recent blog entries. If you go back to my first blog, you'll find that I've trimmed it down a bit since then. I may trim it down even more. As a humble hobbyist with only 10 or so hours a week to devote to doing what I love, this has to be the way it is. It's just reality.

Anyway, I hope this was helpful. Again, it's just my opinion, and I'd love to hear your feedback if you agree or disagree. Thanks!
4 likes 8 comments

Comments

siliconbrain
I totally see myself in you. Almost a year ago I came to the same realizations. :)
January 10, 2012 05:36 PM
Programming020195BRook
What you've stated in this entry is something many programmers forget! Believe me, I've re-done so many level editors, and even some engines because of poor planning. Being a good programmer indeed goes well beyond knowing syntax, but how one applies problem solving, and planning skills to create your programs so you're not spending 12 days re-working your code because it didn't fit in properly.

You would not believe how many games I've refused to work on because they had no design document, or they would out right not create one! Would you build a house with no blue print? Well, maybe a dog house! However, the quality of your work can sometimes go hand in hand with how well you plan and organize a project.

I've never succeeded on any complex programs without some form of a design document, with planning. Setting small goals gives you the satisfaction of moving forward. This truly helps when looking back to what you've accomplished.

For example:

Goal 1 - Create Chat Program

This is horrible! It could take weeks to complete that goal! It should be as follows:

Goal 1 - Design Visual Prototype
Goal 2 - Create Working Input / Output
Goal 3 - Create Login Screen

Ect...

Great article by the way!
January 11, 2012 01:53 AM
Narf the Mouse
This is something I'm only just learning and putting into practice.

And y'know, I really only need four things from the engine I'm trying to build: Mesh display, very simple sprite display,, collision physics and input.

Everything else is simply not necessary for my first project with that engine.
January 11, 2012 02:09 AM
ZachBethel
I'm glad this is ringing true for other people as well.

[quote name='Narf the Mouse' timestamp='1326247754']
This is something I'm only just learning and putting into practice.And y'know, I really only need four things from the engine I'm trying to build: Mesh display, very simple sprite display,, collision physics and input.Everything else is simply not necessary for my first project with that engine.
[/quote]

It's good that you realize that. Try and trim your requirements to fit what you need and leave out the cool fluff until you feel confident you can do it right.
January 11, 2012 02:39 AM
phil_t
Good article.


You alluded to this a bit: building a prototype (you called it a "bogus program") is one of the most useful things you can do. For a large project that requires lots of "design", it can prove invaluable. If you're unsure what kind of abstractions/classes/etc you need to implement something, then just implement it quick'n'dirty (with the expectation you will throw it away). Often the solutions manifest themselves and you are alerted to a bunch of gotchas you hadn't considered.

I tend not to make "official" design documents (working on my own), but I do make scenario lists (e.g. "Monster drops some loot and player gets it and adds to his inventory", or "Find a unique item hidden in a stump"). And I vet my design against those scenarios to make sure they can all be accomplished. I try to flesh out, as precisely as possible, the functionality that is required for each scenario. There are always surprises that pop up as you write the code, but doing this goes a long way to eliminate those surprises.

I used unit-testing extensively at my previous (not game-related) job - I wanted to be sure any component I wrote, when handed off to someone else, worked perfectly and continued to work perfectly (unit tests are great for code maintenance, as they are a sort of design document that you *must* keep in sync with the code - as opposed to what you normally think of as a design document, which always gets out of date). I think unit tests are pretty essential if you're working with others.

For working on my own though, I haven't bothered with them yet. There is definite implementation/maintenance cost to them and I haven't found the cost-vs-payoff to be worth the while for my own projects (so far). YMMV.
January 11, 2012 08:56 PM
evanofsky
"Pick an Achievable Goal and Stick With It"... I've known this is the best way for years. Still can't resist the urge to make a Half-Life 2 killer.
January 14, 2012 03:20 PM
Deyja
If you never aim high, you'll miss the stars every time.
January 16, 2012 03:46 AM
ZachBethel
[quote name='Deyja' timestamp='1326685568']
If you never aim high, you'll miss the stars every time.
[/quote]

My point isn't to never aim high. Ambition and vision is important if you expect to make it in this competitive market. The problem comes when you aim too high too early, without the experience and commitment to back it up. Most of the successful big name companies started small, including Google, Facebook, Id, Microsoft, Apple--the list goes on. They got where they are now by building on their ideas. Also, in my humble opinion, those guys had it easier back then because the market wasn't as established as it is now. What I was discouraging in my blog was the attitude that you can skip all the intermediate steps and go straight for the stars. That just doesn't sound realistic to me; those guys had to start small too.
January 16, 2012 02:26 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement