I think I have learned something valuable recently in thinking about how I will construct my game objects, and I should share. I was considering the implementation details of embedding a physics engine into my objects, and I felt considerable apprehension about using multiple inheritance, though it was the most obvious thing to do. I also considered a templated mixin approach, since I had seen it when using the opensteer pathfinding library for a class project. Eventually, this led me to what I think now is the right answer. The downside of the obvious thing, a crazy inheritance hierarchy, is I’d be making it very hard to change my mind if something were to come up later that I hadn’t planned on, such as a new functionality or ability. I’d have to blow up my interface classes, or make some awful hacks to make it work right. The correct thing to do is to use components and has-a relationships as much as possible within the definitions of classes. Multiple sources reference Design Patterns:
(1) program to an interface and not to an implementation
(2) favor object composition over class inheritance
There must be a good reason these folks that are much smarter than me say this, and I think this commitment to complexity is the issue that made me feel so nervous about adding functionality through multiple inheritance. Simplicity makes life easier. My scene graph structure should not have any idea of the physics details (or sound or whatever), that’s something for the classes to figure out. If I am stingy with my inheritance, I’m less likely to get stuck somewhere along the way or need to hack something. My game objects (scene graph nodes) can have-a physics object just as easily as they can be-a physics object, but the implementation ends up less tied down if I use components where it makes sense. I think it will also give less troubles when I start thinking about multi-threading. For instance, I could have a separate data structures for each type of component (physics objects, sound sources, etc.), and I wouldn’t need to parse the scene graph all the time. Each subsystem would only be exposed to what it needs to in order to do its job. This feels more right.
Some articles I found:
A talking door broke everything: