Yeah, that sounds exactly like what I was getting hung up on with OOP.
I think the problem with OOP started with Java - the way it was taught at
some universities - putting everything in classes mixing code and data at
will while hoping that OOP will make the code modular and reusable by default.
LOL Before OOP (before C++ and Jave) there was modular programming albait
some other languages had OOP for ages - whereas C and Fortran didn't. And
today, one can still learn from the modular programming method; Wiki: Modular
programming [...] is a software design technique that emphasizes separating
the functionality of a program into independent, interchangeable modules, such
that each contains everything necessary to execute only one aspect of the
desired functionality. ...". The cool things start if you program your logic/
methods/algorithms modular and treat your data in an OOP fashion. One of the
best examples doing this is the C++ STL (Standard Template Library). ...
... What is your take on entity systems (as described
here for example? They seem designed to solve the problem of separating data from algorithms, and I've heard nothing but praise in the few articles I've read on them. ...
... And how you group these methods together is up to you, as I've explained
in my last two posts. What Mick West describes here is basically type-fying
modular programming to a certain degree. Removing all the objects and list
stuff he talks about, the concept boils down to;
(based on the concept of game entities being quite similar)
Code:
struct EntityData;
EntityData pd; // player data
pd.position = vec3(0,0,0);
pd.velocity = vec3(1,2,3);
...
void UpdatePlayer(EntityData ed)
{
Position(ed);
Movement(ed);
Render(ed);
Script(ed);
// Target(ed);
Physics(ed);
}
void UpdateTarget(EntityData ed)
{
// Position(ed);
// Movement(ed);
// Render(ed);
Script(ed);
Target(ed);
// Physics(ed);
}
...
Well, that's similar to what I was talking about previously, basic building
blocks grouped by a given logic.
Using objects;
Code:
class EntityData;
class Position : Base
{
Update(EntityData ed)
{
ed.position += ed.velocity*dt;
}
};
class Movement : Base
{
Update(EntityData ed);
};
...
class A_Player
{
EntityData pd;
EntityFunctionList pfl;
A_Player()
{
pd.position = vec3(0,0,0);
pd.velocity = vec3(1,2,3);
pd.render = { VertexList, FaceList, CULL, SHADE, ...};
pd.script = { Idle, Move, Jump, ...};
pd.target = vec3(0,0,0);
pd.physics = { Rigid, ...};
pfl.insert(Position);
pfl.insert(Movement);
pfl.insert(Render);
pfl.insert(Script);
pfl.insert(NULL);
pfl.insert(Physics);
}
Update()
{
for(i=0; i < pfl.end(), i++)
pfl.elem(i).Update(pd);
}
};
Methods and data are kept separated.
Usually we have;
Code:
class B_Player
{
position = vec3(0,0,0);
velocity = vec3(1,2,3);
render = { VertexList, FaceList, CULL, SHADE, ...};
script = { Idle, Move, Jump, ...};
target = vec3(0,0,0);
physics = { Rigid, ...};
B_Player();
void UpdatePosition()
{
position += velocity*dt;
}
void UpdateMovement();
...
Update()
{
UpdatePlayer();
UpdateMovement();
...
}
};
As you can see, B_Player's methods like UpdatePosition are tied to the object.
Sure, one can start to build interfaces, base-classes whatsoever to abstract
it all "away", but this is exactly where the problem with all the deep class
hierarchies starts;
Code:
class B_Player : public Human -> Entity, Drawable, Movable, Pwnable
{
// HELL ↓
}
What Mick West describes (OBJECT AS A PURE AGGREGATION) is just a way of
grouping things. But the primary assumption is the simplicity of the basic
building blocks (components). Starting from these blocks allows to form many
different groupings - fitted for a certain purpose. However, you're never
going to see such possibilities while using way too complex objects at first
instance. That's it.