AxeGuywithanAxe

Cache Coherency and Object Update

Recommended Posts

As far as i'm aware, there are two major paradigms when it comes to game object / game component updating.

The first is updating each "entity" at a time, including it's components"

The second is updating all components of a specific type at once.

The first approach seems to be easier to code , especially when you take into account update dependencies (i.e parent update before child) , but seems to be less efficient in terms of cache coherency and etc.

The second approach seems to be complicated to design , but helps with cache coherency and general optimizations  i.e animating all skeletal meshes at once , performing all navigation queries , etc.

It seems that most game engines , like unreal, that were built a decade + ago have turned their old game object hierarchy into the first approach , but I wanted to ask, if you were creating a game engine today, which approach would you choose?

Share this post


Link to post
Share on other sites

Thank you for the response!

I've actually been thinking about the way i'd handle data layouts. Each component would have what I refer to as "BusData" , bus data contains all of the memory that would be required for updating the component , and each component class also has a class called "BusDataProcessor" , so a skeletal mesh would have SkeletalMeshBusData and SkeletalMeshBusDataProcessor. When an object wants to be updated, it allocates an instance of it's BusData , therefore removing the issue of " you never actually need to update all those components at once" . If there is an allocated BusData in the processor, it is because the component wants to be updated. 

My main issue with the ecs model is that it seems to make certain issues like interobject dependencies , function overloading , and things of that nature more complicated. I've tried to cope with that by doing dependencies on a system basis.I have a "SpatialComponent" base class, which contains a transform/bounds/etc. Examples of the classes that subclass from this are skeletalmeshcomponent, staticmeshcomponent, etc. I also have a movement component and an input component. If the entity is a player , the movement component is dependent on the input component, but if the player is an ai, the movement component is dependent on the aicomponent. I could make it so that the movement component system is dependent on the ai and input component, but you can see how it can become convoluted. 

Share this post


Link to post
Share on other sites
11 minutes ago, AxeGuywithanAxe said:

My main issue with the ecs model is that it seems to make certain issues like interobject dependencies , function overloading , and things of that nature more complicated.

That's because "ECS" is an overengineering trap. These issues are only as complicated as you choose to make them, and you choose to make them more complex by ascribing more magic and dogma to what an "ECS" is than you should. Even your described "bus data" paradigm strikes me as overengineered by virtue of focusing on a generic, one-size-fits-all solution to everything and then trying to cast specific problem scenarios into that mold.
 

 

11 minutes ago, AxeGuywithanAxe said:

I also have a movement component and an input component. If the entity is a player , the movement component is dependent on the input component, but if the player is an ai, the movement component is dependent on the aicomponent. I could make it so that the movement component system is dependent on the ai and input component, but you can see how it can become convoluted. 

But remove "component" from the names of all these interfaces. You are left with the same "convoluted dependency" problem. The issue here isn't the component approach, per se. It's just the same old API interface design problems re-made with different names. The ECS magic bullet has been billed so hard (incorrectly) as a solution to these problems, but it isn't at all. It's a solution to an entirely different problem that gone through some kind of collective-consciousness mutation. Just like scene graphs did, back in the day.

If your agent movement is currently depending on pulling data from either the input system or the AI system, depending on the state of the agent (player controlled versus AI controlled), perhaps the solution is to have something push the movement commands to the agent movement object through the unified single interface of that object. Thus reducing the double dependency by inverting the relationship.

Share this post


Link to post
Share on other sites

I guess maybe I should of focused on the ideology behind ecs than the ecs paradigm in general. The bus data approach helps in the sense that you only load and focus on the data that is required on updating, no cache misses, no etc. I read the gdc presentation in which insomniac increased the speed of their code through smd by just focusing on the simple data that is required for updating.

Even in a game object model , or game object with component, the movement of a character is dependent on input. In UE4 they have a "controller" which is ticked prior to the movement component , through a dependency graph, and pushes commands depending on input , either by the playercontroller or the aicontroller, to the movement component so no matter the paradigm , my ideology is still to push the commands instead of reading. To my point about the "movement component being dependent" it is dependent on the others in that it has to be updated after it's had it's commands pushed, or there will be one frame of latency. 

Share this post


Link to post
Share on other sites

Data access patterns in an ECS are highly unpredictable, since each entity can have different behaviors that require different data at different times. This is entirely at odds with data-oriented design. You'll go mad trying to reconcile the two.

Share this post


Link to post
Share on other sites
14 minutes ago, Zipster said:

Data access patterns in an ECS are highly unpredictable, since each entity can have different behaviors that require different data at different times. This is entirely at odds with data-oriented design. You'll go mad trying to reconcile the two.

I don't know if I necessarily agree. Systems would provide the same update logic that an entity would do, but across all components of the same type at once. So in a game object model, you'd have a SkeletalMeshComponent that does the animation processing in a tick function, in ECS you would have a SkeletalMeshComponentSystem which updates all animations at once , even across threads.

I think the data access patterns are quite explicit. That seems to be one of the biggest advantages over the game object model.

Share this post


Link to post
Share on other sites
56 minutes ago, Zipster said:

Data access patterns in an ECS are highly unpredictable, since each entity can have different behaviors that require different data at different times. This is entirely at odds with data-oriented design. You'll go mad trying to reconcile the two.

If you're doing ECS "properly" (if such a thing can be said to be possible, given the disagreement over what ECS actually means) then you aren't updating each entity every frame, because an "entity" is just a binding mechanism that identifies groups of components. The most common operation should be updating homogeneous lists of components all at once, with operations that touch multiple components being comparatively "rare." Actually accomplishing this can indeed be "maddening" if you aren't used to thinking in those terms and don't have gameplay that's well-suited to that kind of decomposition.

Of course, I would like to point out that you can use non-dogmatic, data-oriented "outboard composition" without locking yourself into dogmatic ECS...

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
3 hours ago, Oberon_Command said:

If you're doing ECS "properly" (if such a thing can be said to be possible, given the disagreement over what ECS actually means) then you aren't updating each entity every frame, because an "entity" is just a binding mechanism that identifies groups of components. The most common operation should be updating homogeneous lists of components all at once, with operations that touch multiple components being comparatively "rare." Actually accomplishing this can indeed be "maddening" if you aren't used to thinking in those terms and don't have gameplay that's well-suited to that kind of decomposition.

Of course, I would like to point out that you can use non-dogmatic, data-oriented "outboard composition" without locking yourself into dogmatic ECS...

I feel like the only maddening aspect I have about is that I can't seem to find a way to maintain the required entity update order (i.e update parent before child) , that is easily achievable in a entity component model , In that method I would just have an entity put it's parent as it's dependencies , and the component's would put it's owning entity as a dependency, and it's done. With system wide updating, it seems impossible in my mind to maintain this. 

Share this post


Link to post
Share on other sites
23 minutes ago, AxeGuywithanAxe said:

I feel like the only maddening aspect I have about is that I can't seem to find a way to maintain the required entity update order (i.e update parent before child) , that is easily achievable in a entity component model , In that method I would just have an entity put it's parent as it's dependencies , and the component's would put it's owning entity as a dependency, and it's done. With system wide updating, it seems impossible in my mind to maintain this. 

My first question would be, why do you need parent before child updating at the component level in the first place? What's the use case for that? Remember, a "component" is ideally a bundle of state that, in the most common operation over that state, is contiguous in memory. Can you rethink your decomposition to avoid the issue?

My second question would be, why can't you just sort the component array to enforce the update order? Or partition it, then update the partition with parents before the partition before children?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
8 minutes ago, Oberon_Command said:

My first question would be, why do you need parent before child updating at the component level in the first place? What's the use case for that? Remember, a "component" is ideally a bundle of state that, in the most common operation over that state, is contiguous in memory.

My second question would be, why can't you just sort the component array to enforce the update order? Or partition it, then update the partition with parents before the partition before children?

 

I think it's mostly based on transform information. For example, let say you have a gun attached to a character at point X . The gun requires the animation of the character to be finished before it updates it's own transformation. Or maybe you have a "master" "slave" animation component, where the animation component just copies the transform information from the master component. 

I think mostly because it would require a resorting for every time you attach and detach an object, it seems somewhat cumbersome.

Share this post


Link to post
Share on other sites
2 minutes ago, AxeGuywithanAxe said:

 

I think it's mostly based on transform information. For example, let say you have a gun attached to a character at point X . The gun requires the animation of the character to be finished before it updates it's own transformation. Or maybe you have a "master" "slave" animation component, where the animation component just copies the transform information from the master component. 

I think mostly because it would require a resorting for every time you attach and detach an object, it seems somewhat cumbersome.

Sounds like a partitioning would be a better option than sorting, then. More lightweight than sorting AND you can do it in a way that clearly shows in the debugger which components are parents and which are children.

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
3 minutes ago, Oberon_Command said:

Sounds like a partitioning would be a better option than sorting, then. More lightweight than sorting AND you can do it in a way that clearly shows in the debugger which components are parents and which are children.

Could you give me an example of partitioning components? I don't think I understand what you mean by it.

Share this post


Link to post
Share on other sites
19 minutes ago, AxeGuywithanAxe said:

Could you give me an example of partitioning components? I don't think I understand what you mean by it.

Well, for starters, this assumes that you keep your components in some kind of contiguous sparse array, where the components' "physical indices" don't need to be the same as their "logical indices" (ie. their entity identifiers), hereafter referred to as a "component container."

The brute force way you could do that would be to have two entirely separate, hardcoded component containers. When you update the components, you'd run the same update loop on both containers, one right after the other.

This is a bit off the top of my head, but suppose you could keep them in the same array, but just arrange the elements such that parents always come before children, and the rest of the ordering doesn't matter? So (for example), you might have the first 5 components be parent/childless components, and the next 3 be child components, and keep a "physical" index to the first child component. 

Re-parenting a component would just mean swapping components around. You make one of the parent components a child component by swapping the new child with the last parent, then decrementing the physical index to the first child component. You unparent a child component by swapping the child component with the first child, then incrementing the physical index to the first child component. This way, the parents and children still live in contiguous memory and you still have O(1) parent/unparent operations.

Of course, this requires that your components be stored in contiguous memory even when there are deleted components, that they be able to be swapped in memory, and that you never take pointers to components.

Edited by Oberon_Command

Share this post


Link to post
Share on other sites

I don't think that would work in the current component system I have set up. Currently my hierarchy is like this :

  CEntityComponent (base class of all components)

    - CSceneComponent (base class of all components with a local/world transform and bounds)

      - CDrawableComponent ( base class for all components that should be registered with the renderer)

         - CSkeletalMeshComponent ... etc..

 

It seems that your approach is for systems that have one "CTransformComponent" . In my engine, a static mesh can be attached to a skeletal mesh , these two items would be in completely different systems, making your approach impossible.

Share this post


Link to post
Share on other sites
32 minutes ago, AxeGuywithanAxe said:

I don't think that would work in the current component system I have set up. Currently my hierarchy is like this :

  CEntityComponent (base class of all components)

    - CSceneComponent (base class of all components with a local/world transform and bounds)

      - CDrawableComponent ( base class for all components that should be registered with the renderer)

         - CSkeletalMeshComponent ... etc..

 

It seems that your approach is for systems that have one "CTransformComponent" . In my engine, a static mesh can be attached to a skeletal mesh , these two items would be in completely different systems, making your approach impossible.

Indeed. With my approach (and the ECS approach), there would also be no inheritance hierarchy, and components would be pure or nearly-pure data. ;)

Just based on that inheritance hierarchy, I'm assuming you store your components in heterogeneous containers in your game objects? That's going to be difficult to make cache-coherent, I think. 

I'm also wondering what a "component" represents in your system. Deep inheritance hierarchies on components seems unusual, given that an advantage of using components is getting away from deep inheritance hierarchies. What are you getting out of this decomposition?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
21 minutes ago, Oberon_Command said:

Indeed. With my approach (and the ECS approach), there would also be no inheritance hierarchy, and components would be pure data. ;)

Just based on that inheritance hierarchy, I'm assuming you store your components in heterogeneous containers in your game objects? That's going to be difficult to make cache-coherent, I think. I'm also not sure this is the best use of inheritance, now that I think of it - just because some objects conceptually share properties doesn't mean they physically need to share them.

I'm also wondering what a "component" represents in your system. Deep inheritance hierarchies on components seems unusual, given that an advantage of using components is getting away from deep inheritance hierarchies. What are you getting out of this decomposition?

Ah.. I'm not exactly ready to make that jump.

Hiearchal components Is a model that I see game engines like, unreal , cryengine, lumberyard, decima, and etc use and personally it makes more sense to me. There are a lot of components that in some sense contain similar logic. I.e a skeletal mesh component and a static mesh component. They both require a transform, they both require a render proxy(my engine is multithreaded so the render thread has a version of each "drawablecomponent" which provides draw logic. They both need a way to sync data to the rendering thread, so there is a lot of logic that they share, in reality, the only difference they have is in their "update" function. My hierarchies aren't exactly deep though, they just exist and make maintenance of code a lot easier. They definitely have an issue with cache coherency, which is what I was trying to get at when talking about the benefits of ecs.

Share this post


Link to post
Share on other sites

In my world, more than one level of inheritance is "deep inheritance." And I use implementation inheritance extremely rarely - interface inheritance happens more often, but is still only one level deep.

If your inheritance is just about code sharing, you could implement more or less the same architecture using composition - instead of inheriting, you'd have your CSkeletalMeshComponent contain components of the previous types and delegate to them. You should only use inheritance if you need to be able to take a pointer to a CSkeletalMeshComponent and use it like it's a CSceneComponent instead. Do you really need that, or can you just register the CSceneComponent with a system that deals with those components without caring about what object contains it?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
4 hours ago, Oberon_Command said:

If you're doing ECS "properly" (if such a thing can be said to be possible, given the disagreement over what ECS actually means) then you aren't updating each entity every frame, because an "entity" is just a binding mechanism that identifies groups of components. The most common operation should be updating homogeneous lists of components all at once, with operations that touch multiple components being comparatively "rare." Actually accomplishing this can indeed be "maddening" if you aren't used to thinking in those terms and don't have gameplay that's well-suited to that kind of decomposition.

Why should such an operation be the most common? If a system needs to read data from N components in order to update one, then so be it. There's no conclusion you can draw from this. Even from a performance perspective, there will be little difference on modern caches between accessing multiple arrays in sequence versus accessing their elements interleaved. And if you ever each the scale where it matters, you'll have much bigger issues to deal with.

What you should be more worried about is handicapping the design of your components and systems to meet unnecessary requirements, and making it that much harder to actual implement non-trivial gameplay with the ECS. It defeats the purpose of having one if you can't do what you to with it, and ultimately cause the kind of coupled spaghetti code mess you were trying to avoid in the first place.

Share this post


Link to post
Share on other sites
1 hour ago, Oberon_Command said:

In my world, more than one level of inheritance is "deep inheritance." And I use implementation inheritance extremely rarely - interface inheritance happens more often, but is still only one level deep.

If your inheritance is just about code sharing, you could implement more or less the same architecture using composition - instead of inheriting, you'd have your CSkeletalMeshComponent contain components of the previous types and delegate to them. You should only use inheritance if you need to be able to take a pointer to a CSkeletalMeshComponent and use it like it's a CSceneComponent instead. Do you really need that, or can you just register the CSceneComponent with a system that deals with those components without caring about what object contains it?

I don't know , that seems like a lot of convoluted steps to reflect inheritance in my opinion. The skeletal mesh component is a subclass because it has a special tick function (performs animation) , and allocates a special render proxy that knows how to render skeletal meshes (CSkeletalMeshRenderProxy) , it also knows what data it needs to send to the rendering thread. Each drawable component has this type of specific logic.

Share this post


Link to post
Share on other sites
1 hour ago, Zipster said:

Why should such an operation be the most common?

Because of Amdahl's law - you want your most common operations to be cache-friendly because you get the most overall decrease in latency by optimizing the parts of the program that take up most of its execution time. Practically, this tends to mean designing your data layout in such a way that your access patterns minimize cache misses. It's not so much that such operations are the most common, so much as you could structure things such that you make them the most common.

1 hour ago, Zipster said:

What you should be more worried about is handicapping the design of your components and systems to meet unnecessary requirements, and making it that much harder to actual implement non-trivial gameplay with the ECS. It defeats the purpose of having one if you can't do what you to with it, and ultimately cause the kind of coupled spaghetti code mess you were trying to avoid in the first place.

I agree in principle, but OP is asking about cache coherency and how to structure his program in a way that's cache-friendly...

1 hour ago, AxeGuywithanAxe said:

I don't know , that seems like a lot of convoluted steps to reflect inheritance in my opinion.

It's not that they're reflecting inheritance, it's more that implementation inheritance is reflecting a special case of composition. 

Does a car have wheels, an engine, and a steering wheel, or is it a SteerableGasolinePoweredVehicle which is a GasolinePoweredVehicle which is a Vehicle?

Suppose I want a drawable component that isn't positioned in the scene or even a skeletal mesh that isn't in the scene, but is instead a UI element drawn at a fixed screen position? Do I have to create a CSkeletalMeshComponentForUI class? What should that derive from? And why do I care that a CSkeletalMeshComponent can be placed in the scene if my code doesn't deal with the scene, anyway? Suppose I'm writing code that only cares about the mesh and shouldn't care where it is, or even that it's renderable?

As I understand it, it's actually the current thinking in the object-oriented world at large to prefer composition over inheritance. Deep inheritance hierarchies are considered a bit of an anti-pattern nowadays. Most "is-a" relationships are better modelled as "has-a" relationships - a "CSkeletalMeshComponent has a transform" is more straightforward to understand, less coupled, and is less design restrictive than "CSkeletalMeshComponent is a drawable-compononent-with-a-transform."

To go back a bit:

3 hours ago, AxeGuywithanAxe said:

Hiearchal components Is a model that I see game engines like, unreal , cryengine, lumberyard, decima, and etc use and personally it makes more sense to me.

I encourage you to try other models. Just because some major engines use this kind of hierarchical design doesn't mean you need to - or even should. Big engines tend to be big due to exposure and inertia and featuresets - you know, the business stuff - not because their gameplay architectures are superior.

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
4 minutes ago, Oberon_Command said:

Suppose I want a drawable component that isn't positioned in the scene or even a skeletal mesh that isn't in the scene, but is instead a UI element drawn at a fixed screen position? Do I have to create a CSkeletalMeshComponentForUI class? What should that derive from? And why do I care that a CSkeletalMeshComponent can be placed in the scene when my code doesn't deal with the scene, anyway? Suppose I'm writing code that only cares about the mesh and shouldn't care where it is?

Actually my ui elements would be inherited as :

    CEntityComponent 

       - CUIElementComponent

They don't need the 3d transform (3d position , 3d scale, and 3d quat rotation) , so they would have no reason to subclass from CSceneComponent , and they are not meshes that animate, so they would have no reason to subclass from CSkeletalMeshComponent.

CSceneComponent/CDrawableComponent are for component's that will be placeable in the world, i.e static meshes , skeletal meshes, terrain , water, etc.... So i don't think there is any thing restrictive about it. 

The "has-a" relationship is still maintained, just not as fine grained as you specify.   The SkeletalMeshComponent is a drawable component which has a skeletal mesh and the scene component is a component which has a transform. I don't think the point of composition over inheritance is to remove all inheritance, it is to move further towards the one job principle , and better separation and code usage. 

The purpose of the base classes (CDrawableComponent/CSceneComponent) is to reduce the amount of unnecessary code bloat. Every skeletal mesh component needs to be movable, just like all other objects that are placed in the world, so why rewrite the same Set(Relative/World)Position/Get(Relative/World)Position/etc code for each class just to avoid inheritance?  

To the last point, I know that Unreal Engine is not the best example of cache coherency , that's why I also included other engines with available information , either from GDC or github. I have yet to see an engine that almost completely forgoes inheritance in the way you say, and has not become more complicated and bloated because of it. Even Insomniac Games , which has Mike Acton at the helm, use inheritance in their component model .

Share this post


Link to post
Share on other sites
16 minutes ago, AxeGuywithanAxe said:

I don't think the point of composition over inheritance is to remove all inheritance, it is to move further towards the one job principle , and better separation and code usage. 

The point is to prefer composition over inheritance. To me, that means that if you can do something without inheritance, and your code quality doesn't suffer for it, then you should. Composition rather than implementation inheritance is almost always a better way to achieve less coupled, more focused classes.

It has been my personal and professional experience that the use of deep implementation inheritance has a tendency to lead to code that is brittle and difficult to maintain. Granted, I've spent 90% of my career on big legacy C++ codebases - but most newer code, even within those codebases, tends to use inheritance very sparingly rather than making it the centerpiece of the architecture because of how easily we know it can be misused. I'm talking something like 7-8 levels of inheritance on these old things which is downright pathological...

16 minutes ago, AxeGuywithanAxe said:

 

The purpose of the base classes (CDrawableComponent/CSceneComponent) is to reduce the amount of unnecessary code bloat. Every skeletal mesh component needs to be movable, just like all other objects that are placed in the world, so why rewrite the same Set(Relative/World)Position/Get(Relative/World)Position/etc code for each class just to avoid inheritance?

  1. Why does inheritance do that better than composition in this case? Why can't you just have a transform component that each of the components contains that does all that positioning stuff, without coupling the components' identities to the fact that they're transformable?
  2. You misunderstand; it's not a case of doing it "just to avoid inheritance," it's that composition is the default when designing new classes. From my point of view, most implementation inheritance is doing inheritance just to avoid composition!
  3. The purpose of inheritance isn't not to repeat code, it's to express "is-a" relations where an object must be treated as an object of its parent type. I suspect most modern OOP adherents would say that using inheritance to avoid repeating yourself is the wrong mindset entirely.

 

16 minutes ago, AxeGuywithanAxe said:

To the last point, I know that Unreal Engine is not the best example of cache coherency

I'm not even talking about cache coherency, I'm talking about architecture in general.

16 minutes ago, AxeGuywithanAxe said:

I have yet to see an engine that almost completely forgoes inheritance in the way you say, and has not become more complicated and bloated because of it.

And I have yet to see the internals of an engine that uses more than 1-2 levels of implementation inheritance that has not become complicated and bloated because of it. :)

Edited by Oberon_Command

Share this post


Link to post
Share on other sites
15 minutes ago, Oberon_Command said:
  • Why does inheritance do that better than composition in this case? Why can't you just have a transform component that each of the components contains that does all that positioning stuff, without coupling the components' identities to the fact that they're transformable?
  • You misunderstand; it's not a case of doing it "just to avoid inheritance," it's that composition is the default when designing new classes. From my point of view, most implementation inheritance is doing inheritance just to avoid composition!
  • The purpose of inheritance isn't not to repeat code, it's to express "is-a" relations where an object must be treated as an object of its parent type. I suspect most modern OOP adherents would say that using inheritance to avoid repeating yourself is the wrong mindset entirely.

1) I don't understand the benefit of taking that approach. If a skeletal mesh component has a transform component , or a skeletal mesh has a position and rotation through inheritance, they're identities are still coupled to the fact that they are transformable, all this approach would achieve is adding an unnecessary indirection. Taking a position and a rotation and putting it in a separate class does not remove the fact that a skeletal mesh must be transformable.

2/3) I think we may just have a fundamental difference in how we view OOP. The "is-a" relationship exists to show that an object has similar characteristics to a parent class , thereby reducing code bloat. I don't think it's possible to separate the two. You create base classes because of shared functionality , without this shared functionality, there would be no need for OOP.

Yeah , I meant to say architecture and not cache coherency

I don't know about that, I think we'd just have to agree to disagree! haha. There are many avenues in which objects share the same functionality , i.e (they are a component - > they have a transform -> they are usable in the renderer scene). I believe that it's because people are using OOP the wrong way, that it becomes convoluted, i.e making a "CSkeletalMeshComponentForUI" instead of a "CUIElementComponent". 

Share this post


Link to post
Share on other sites

Ok, I'm not sure how useful my reply is here (I'm too lazy to read through all comments), but just keep in mind that composition versus inheritance is more than just a technical thing. It's a readability issue as well as a "use as needed" thing as jpetrie pointed out. Sometimes, they're incomparable. I mean, what's best - driving a car or eating a hamburger?

A platipus lays eggs and has a duck beak, but it's a mammal. Evolution and emergence aren't always inherit-friendly. Try designing a platipus-type object using inheritance only, without resorting to repeated code or multiple inheritance (which I, as an amateur, hear from people = pure evil).

Also, a Command Pattern is useful when you have unrelated objects of very specific shared attributes like Move(), TurnOn(), Fly() or w/e that, abstractly, do the exact same thing (e.g. "Move()"), but concretely are different from eachother (e.g. "MoveInDrunkenStupor()". So there's abstraction and decoupling involved. When you tell X.Fly(), it flies differently way than if you tell Y.Fly(), because you've used a hierarchy of interfaces as a middle man and defined two different Move() functions - FlyLikeABird() and SwimLikeAFish(). But the Move() function of both X and Y are still both just Move().

Command patterns explained:
https://en.wikipedia.org/wiki/Command_pattern

But you tell me. It all depends on how many different kinds of objects that you want to give certain shared attributes. Choosing whether you use inheritance or composition (or both, or neither) for a given task should come intuitively to you. "Can I fit this ability into an existing Inheritance tree?" If yes, then do it. If not, then use composition. If both methods require too much coding for the simplest thing, use neither. If your component hierarchy is complex enough, perhaps use both.

Again, sorry if my comment is totally missing the mark. I'm no expert though, so I may be mistaken on some things.

Edited by Madolite

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now