Design question

Started by
13 comments, last by Servant of the Lord 11 years, 6 months ago
Is it smart to design classes for a game using design composition? I think its called composition. The methods used on this page http://gameprogrammi.../component.html
Advertisement
Yes, composition is applicable and useful for games.

- Jason Astle-Adams

Is it overall a better choice? Does it have it's pro's con's? Is it better for only some games? Just trying to get an idea about composition.
All design is a matter of tradeoffs. If your game would make good use of it then it's a good idea. If the game won't, then it might not be.
That article is talking about Component Based Design, not Composition, though it did slightly mix some Composition into the article and didn't exactly clarify the difference.
Composition is not Component Based Design, and Component Based Design doesn't always use Composition.

This is composition:
class Cat
{
Teeth teeth; //Generic 'Teeth' stuff.
Tail tail; //Generic 'Tail' stuff.

//'Cat'-specific stuff.
std::string name;
Color furColor;
};

class Dog
{
Teeth teeth; //Generic 'Teeth' stuff.
Tail tail; //Generic 'Tail' stuff.

//'Dog'-specific stuff.
std::string name;
Color hairColor;
int hairLength;
Breed breed;
int weight;
};

Cat is then "Composed of" Teeth, a Tail, a string, and a Color.
Dog is also "Composed of" Teeth and a Tail, and also other things. Teeth and Tail are re-usable and don't directly know about either Cat or Dog classes.

It is an alternative to inheritance:
class Animal
{
//Inherited 'Animal'-specific stuff.
Teeth teeth;
Tail tail;
};

class Cat : public Animal
{
//'Cat'-specific stuff.
std::string name;
Color furColor;
};

class Dog : public Animal
{
//'Dog'-specific stuff.
std::string name;
Color hairColor;
int hairLength;
Breed breed;
int weight;
};


Some people use the general rule-of-thumb:
"Composition means 'has-a'. Inheritance means 'is-a'.".
A Cat 'is-a' Animal? Or a Cat 'has-a' Tail and Teeth?

Composition should be prefered over Inheritance, unless inheritance's pros are actually needed.
Inheritances pro's are that you can treat a Cat class as if it is an Animal class. So you can treat a Cat and a Dog using only their Animal interfaces, and handle their Animal-common interface in a single way without knowing the details of a Cat or a Dog class. The Animal interface becomes a way to interact with both Dog and Cat in a uniform way.

Component Based Design is something different, and not directly related to the idea composition vs inheritance. It can be implemented using composition, or using inheritance, or using neither. It's not (directly) related to that subject.

This is Component Based Design:
class MovementComponent
{
void MoveTo(Position);
}

class DisplayComponent
{
void SetModelToUse(Model);
void Draw();
}

class SoundComponent
{
void SetNoiseToUse(Sound);
void MakeNoise();
}

class Entity
{
std::string name;
MovementComponent movementComponent;
SoundComponent soundComponent;
DisplayComponent displayComponent;
}

Entity entity;
entity.name = "Fido the Dog"
entity.displayComponent.SetModelToUse("../data/DogModel.model");
entity.soundComponent.SetSoundToMake("../data/BarkLoudly.wav");

entity.movementComponent.MoveTo(foodBowl);

In the example above I happen to use composition to let Entity know about the different components, but there are a half-dozen ways of doing Component Based Design, some making Entity have a vector of AbstractComponents (using inheritance), so you can add components dynamically.
Some don't even have an explicit Entity class at all, instead using IDs and make components know what ID they belong to, with no actual Entity that contains the components (and the component's lifetime is then managed by a "SubSystem" for each component-type... thus neither Composition nor Inheritance of the actual Entity, because 'Entity' wouldn't exist except as a concept. Each component would instead be controlled (by Composition) with the SubSystem instead)

Composition and Inheritance are class-level implementation details. What is Class composed of, and how?
Component Based Design is slightly higher-level architectural design: How do you manage the individual objects of the game?

It's a different subject entirely, so it'd be good for you to read up on each different subject, so you don't accidentally get the article's confusion of the two entirely different topics mixed together. Object composition vs Object inheritance is one subject. An entirely different subject is Component Based Design vs Data Based Design vs Object Oriented Design vs Event Driven Design, and how they can actually all be used to different extents in a single program.
Ohhh wow, haha more than i thought. And if i understood it correctly you were saying the pros for inheritance was when it was being used for polymorphism?

Also would it be a bad idea to mix composition with inheritance? It seems like in there should be a base object for everything just incase you ever do need to group them.
Inheritance almost always uses composition. The inherited class has to be composed (composition) of something, unless it's just functions.

Also, usually the derived class adds more than just the inherited class' variables, so any derived class is almost always inheriting and? composing (again: unless it's just adding functions).

Example:
//This class is composition only, even though other classes inherit it.
class BaseClass
{
//Composition:
std::string stuff;
int moreStuff;
MyStruct otherStuff;
};

//This class has inheritance AND composition.
class DerivedA : public BaseClass
{
//Composition:
std::string additionalStuff;
};

//Functions don't typically count as composition, so this class is inheritance only.
class DerivedB : public BaseClass
{
void myFunc();
};


In the code above, BaseClass is only using composition, but not inheritance. DerivedA is using both composition and inheritance. DerivedB is only using inheritance (since it doesn't add any member variables).

This class uses neither inheritance nor composition:
class ClassWithFunctionsOnly
{
void myFunc();
void myOtherFunc();
};

(Arguably, that class would be better off as functions within a namespace instead of a class - but it could legitimately be an abstract base class if one or more functions were virtual)

Yes, the primary pro of inheritance is polymorphism. The cons really start showing up when people go inheritance-crazy (defaulting to inheritance instead of defaulting to composition), and end up creating dozens upon dozens of abstract classes that aren't really needed by their program.
Abstract classes are classes that cannot be used themselves but define the common interface for other classes to use, for polymorphism. One of the goals of programmers is to make most of your code re-usable. This is good. However, in the quest to make code re-usable, many programmers get carried away with creating overly generic solutions that aren't really needed, and don't bring them closer to completing their project. sad.png

In the big picture, programming happens in layers. Each layer of code helps hone down from the generic (libraries, engines, and frameworks) to the specific (your project). If the code you are writing is too generic, it'll just be another layer of code between the libraries and your end-goal, without actually carrying you further towards that goal. When abstract programming goes too far, you end up just creating another framework ontop of whatever you are already using, thinking you are making your game, but really just making the unneeded framework that you'll eventually actually build your game upon... if you ever complete it, now that you wasted so much time accomplishing the nothing-framework that looks like something impressive. dry.png

There's an important balance between creating generic code that can be reused in other projects and creating specific code that actually furthers your current project. wink.png

That article is talking about Component Based Design, not Composition

That'll teach me to actually read rather than giving a quick skim. Thanks for taking the time to give a more detailed explanation! smile.png

- Jason Astle-Adams

Heheh, I had to read the article twice to be sure. laugh.png
There was a little ambiguity with the writing as the author semi-mixes the descriptions of both together.
So would this be a good way for drawing many objects?


class Drawable
{
int draw()
{
//Code
}
}
int main()
{
List<Drawable> items;

for (int index = 0; index < items.size(); ++index)
{
items.at(index).draw();
}
}

This topic is closed to new replies.

Advertisement