Tispe, on 07 Jun 2013 - 20:44, said:
Lets take an "Entity class".
members:
-Position
-Health /* Wrong */
-Ammo /* Wrong */
-Skeleton /* Wrong */
-Mesh /* Wrong */
methods:
-Move() /* Somewhat less wrong, indirectly */
-Shoot() /* Wrong */
-TakeDamage() /* Wrong */
Why would a building have health, be able to shoot, or take damage?
Why would a skybox have a skeleton?
You won’t understand what the single-responsibility principal means unless you understand what it means to have a single responsibility.
A CEntity is the lowest-level thing that gets into your game world. Every single object inherits from it. It has 1 job and 1 job only: Provide things with a parent/child relationship.
Next level up you have a CActor, which provides things with world/local orientations.
I didn’t mark your suggestion that an entity have a position wrong because an entity and actor are often combined into 1 and the line between them is ambiguous.
So the only thing every single object in your game world has in common is that they can be parented under each other and they have a local position, which gets translated into a world position whenever changed.
How could you give a health bar to every single object in your game? Does the ground have health? Do buildings explode if you punch them enough?
At this level, we haven’t even gotten to models yet.
CModelInstance -> CActor -> CEntity
Now we have an actual mesh, which can represent some physical objects in the scene.
CDrawableModelInstance -> CModelInstance -> CActor -> CEntity
Now we have physical objects that can be drawn. Remember, not every object is visible. Invisible walls obstruct your path just as well as any other objects do.
CPlayer -> CDestructable -> CDrawableModelInstance -> CModelInstance -> CActor -> CEntity
CGenerator -> CDestructable -> CDrawableModelInstance -> CModelInstance -> CActor -> CEntity
CGiantMoth -> CDestructable -> CDrawableModelInstance -> CModelInstance -> CActor -> CEntity
Now we have something that can take damage. And it took 6 classes to get there.
This is Single-Responsibility Principal. It means a class should do only when it needs to do. It may do more than one thing, of course, as long as it makes sense for it to do that. A CModelInstance can be animated and thus have a skeleton. Because we all know that things may move even if we can’t see them. It makes sense for animation to be part of CModelInstance rather than CDrawableModelInstance. And this is a balance between “is a” and “has a”.
This is Single-Responsibility Principal. Things may have more than one duty, but those duties are logically a part of the object, and may even be delegated to a member of that object. For example a CModelInstance introduces the concept of animation to an actor, but a CSkeleton is the class that actually performs everything related to animations.
Likewise, an actor does not handle the responsibility of moving just because it introduces the concept of a position into the mix. The position, scale, and rotation of anything in the world is handled by the COrientation class. A CActor may introduce local positions to objects, but managing those positions is not its responsibility—that falls to COrientation.
This is Single-Responsibility Principal.
L. Spiro