Public Group

# Better code structuring help for beginners

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

## Recommended Posts

I've written code in javascript, Java, PHP, C, C++, MFC(yuck!) VB and have at least looked at C#. By that list, you might say "Oh, he knows what he's doing." but I don't! The problem isn't particular code snippets. I can make a really ugly looking game entirely in C with all global variables. It'll work, but I wouldn't want to be the poor bastard debugging it. Things like Abstract Object Factories and the like I mostly understand from working on other applications, but I need some CODE! Even I am guilty of giving beginners fatally vague advice like "Oh, you need to iron out your design document first." or "You should have a little more OOP in there." You're probably bored reading this by now, so BOTTOM LINE: Could we start a new forum / article category dealing specifically with how to structure programs, or perhaps expand on that in the Software Engineering category? Most importantly, would some more experienced game programmers be willing to donate their time to creating some really concrete examples?

##### Share on other sites
Seriously, guys...seriously.

No, really, I think this is a good idea. Really I'm building off something I read in a thread a few weeks ago where Oluseyi posited that this site could be more useful if there were some kind of "knowledge map" to guide users in steps.

One of the things I'm having a hard time finding for myself is exactly how to various classes and abstract concepts relate to each other in actual code.

The section on Software Engineering seemed a bit more formal and a bit less concrete than I was hoping for. Does anyone know if there are already relevant articles on the subject?

##### Share on other sites
There aren't so many articles already. Probably the closest you can get is Design Pattern discussions, though [imo] those aren't particularly beneficial to beginners.

I'd be certainly willing to help, though I'm perhaps not the experienced sort you're looking for. Can you povide an example of an abstract concept or structural snafu you ran across which lead to this sort of query?

##### Share on other sites
Quote:
 Can you povide an example of an abstract concept or structural snafu you ran across which lead to this sort of query?

Well, that's just the problem, it's not a particular thing that I'm confused about. It's how to put it all together. I'd like to play around with building an OOP game engine, and I have most of the objects and classes in place, but I'm not quite sure how to get them to interact in an OOP way.

Really, it's just the whole direction of the help we provide. (By "we" I mean the gamedev community in general, 'cause I'm not really that helpful! lol)

I think a lot of things like what classes to put in what files and what kind of code to use for the objects to interact would be nice. I've been programming for a few years now, and I'm not even sure what the purpose of an interface class is (i.e. IUnknown for a COM object)

I know I'm not being helpful in my questions, but that's the problem I'm having: putting abstract concepts into concrete terms. Maybe I just need to understand the implementation of OOP better in general.

##### Share on other sites
It sounds like you should read (or at least have a look at it) "3D Game Engine Programming" (From course PTR. . . heh dont rely on the cd working but anyway...)

It starts off with a great explanation of interfaces!

##### Share on other sites
The Design Patterns book gives some reasonably concrete examples. Abstract factory is in there, for example.

But structuring a program as a whole is not, I believe, something that can be easily taught to you. This is why I think coding is closer to an art or craft rather than a science. Much as with painting a picture, someone can teach you the overview, and they can teach you the technique, but they can't really teach you how to paint a specific picture.

Generally it really is about taking a few abstract concepts and stringing them together in a way that suits your app, and that way may not apply to every app you create. The key is in learning to map those abstractions onto real problems. The book I mentioned helps with this. Practice helps too.

As a simple set of guidelines, I have some classes for entities and some classes for systems. The system classes tend to create, modify, query, and destroy the entity classes. Sometimes I use a state machine within each system, or to manage sub-systems. This tends to either be done with a switch statement or the State design pattern, also in the book above. Anything else... depends totally on what I'm writing.

You might want to look at particular problems in your code. You have globals... why? Can they be local to one system or entity and passed as parameters instead? Could several associated variables be combined into one object? Perhaps a Singleton with a function interface would be better than accessing a global variable directly? Of course, you need a good appreciation of why globals are bad before you can remove them in obvious and helpful way. Much of OOP makes sense when you truly understand why it is there.

##### Share on other sites
Thanks for the help, guys.

@Kylotan: Who's the author of the book you recommend, or perhaps the year of its most recent publishing? Plus, being desperately crushed under the iron heel of poverty in Dick Cheney's America™, are there any free online sources you'd recommend?

P.S. The biggest problem I have is figuring out how to put together the event queue and scripting system. Are there any resources for source code on FF-style RPGs?

##### Share on other sites
I concur with Kylotan. This is one of the really big things that experience brings. I know that I often disdained the emphesis put on experience when I was younger. Knowing syntax and how to solve problems is enough, right? Heh, not exactly.

Anyways, let me see if I can find some code, and describe something I changed recently which really helped me.

Quote:
 I've been programming for a few years now, and I'm not even sure what the purpose of an interface class is

This I think is one of the primary problems you currently have.

The thing which I changed recently, which really helped quite a bit, was to start designing classes around their interface, rather than their data. Straightforward enough. But lets get some concrete examples.

Say you had an object whose sole purpose was to render text to the screen. Now, let's ignore absolutely everything complex about that, and focus on one of the simpilest parts. In that class, how would you store the text?

Unfortunately, almost every single class/object/oop tutorial in the world will have you make something like this:

class  text_renderer      // perhaps inherit from a base renderable                    {private:      string   txt;protected:public:      // render functions      // get/set txt};

In my current opinion, this is terrible. This is a good example where the class [txt] is being designed around the data [a std::string] rather than what it provides [text]. Why is that important? Well, we'll see in a second.

But first, let's see a design which focuses on providing text, rather than being a string.
class   rms_text{private:protected:public:        virtual string  str()=0;        virtual void    str(string s)=0;        virtual const   string  *txtref()=0;        virtual ~rms_text(){}};

This is your standard interface class. It defines an interface where a string is provided [in 2 ways], and may be set. Doing it this way allows the text_renderer to only store a pointer to this interface. In that way, you may then supply different classes which inherit from this interface, and provide a string in many different ways, and the text_renderer won't care about how you do it, as long as you abide by the interface.

C++'s really cool features [inheritance, templates] really only work well around classes that function. Classes that are just data often overlap their function with other classes. Look around on these forums, and count how many threads pop up regarding 'how to I make a function that takes any class?'. That's poor design. Any classes with shared functionality, should share a common class. Otherwise you're duplicating functionality, and thus duplicating code. A waste of time and effort only to get less reliable code.

Back to the example. So, let's provide two common extensions of the interface. The first is the simple scenario where the text is stored in a string.

class   stored_text:        virtual public  rms_text{private:protected:        string  txt;public:        const string    *txtref(){return(&txt);}        string  str(){return(txt);}        void    str(string s){txt=s;}        stored_text(string s=string("")):txt(s){}        virtual ~stored_text(){}};

Not terribly complex, and if this is all you'll ever use, there's no real point in making 2 extra classes just to store a string! But what if you want to not store the string? What if you only want to print out a string stored in another class? Then you create another extension of the interface:

class   reference_text:        virtual public  rms_text{private:protected:        const   string  *txt;public:        const   string  *txtref(){return(txt);}        string          str(){return(*txt);}        void            str(string s){return;}        reference_text(const string *s):txt(s){}        virtual ~reference_text(){}};

And the wonderful thing here is that the text_renderer can now use either, since it only cares about the interface! It can focus on rendering text, and not duplicate code meant to provide text.

Interface classes are also exceptionally useful with templates. Since there can be a practically infinate number of template instances, all which are different types, it is impossible to manually extend things that use the common functionality of all of them.

Here's a good example:
template <typename T>class   reference_data:        virtual public  rms_text{private:protected:        const T         *data;        string          buffer;public:        const   string  *txtref(){return(&buffer);}        string          str(){                if (!data){buffer=""; return (buffer);}                stringstream    ss;                ss << *data;                buffer=ss.str();                return(buffer);        }        void            str(string s){return; }        reference_data(const T *t): data(t){}        virtual ~reference_data(){}};

And since this templated class inherits from the interface class, every single instance can be accessed in text_renderer by a simple rms_text *. The renderer can effectively ignore the template, while reaping the great benefits of it.

By designing around the interface of a class rather than the data, we've gone from one class which renders a string, to one class which textually renders anything which defines an ostream operator<<

##### Share on other sites
Quote:
 Who's the author of the book you recommend

The book he's talking about is Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 27
• 16
• 10
• 10
• 11
• ### Forum Statistics

• Total Topics
634101
• Total Posts
3015528
×