Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualJTippetts

Posted 30 May 2013 - 06:14 PM

Huh. Message-passing is a very loose form of coupling, but it's still coupling. What happens when the semantics of your messages change? That equates to an interface change on the components listening for particular messages. What if you have a component, HealthComponent, that listens for ApplyDamage events; but then, at some point, you add an intermediary ReduceDamage component that acts as a damage shield? At that point, you have to either rewrite the semantics of ApplyDamage and add another event type, something like ApplyModifiedDamage, in the process modifying the interfaces of any components that listen for ApplyDamage. Additionally, this line...
 
zombie->GetComponent("CombatAnimationsController")->OnStateChanged.Bind(zombie->GetComponent("AnimatedModel"), AnimatedModel::ChangeAnimation);
...indicates that you are doing a tighter coupling than simple message-passing, given that someone needs to know enough about the receiver (AnimatedModel) to know that it has a ChangeAnimation method; a true message-passing system wouldn't even be that tightly coupled. It wouldn't know, nor care, exactly which method the receiver uses, if any, to respond to a particular message. Only the receiver would need to know that detail, not some third party hooking up wires.

I worry that you are trying to get too flexible with your paradigm here. Every layer of software on your machine needs to abstract away the messy, intimate details of lower layers so that the higher layers that rely upon it don't have to do as much low-level work; that means that each layer should actually restrict what can be done with it in comparison to lower layers. That is the way of computer science. Imposing limitations, setting requirements, harnessing the generic power of the underlying hardware and turning it toward specialized purposes, is the very heart of what we do. By definition, though, that means that by trying to give the users of your particular layer too much flexibility and power, you actually render your layer useless. What point having an infinitely flexible layer to work with, when they could just eliminate your layer and do everything on the layer beneath? Especially considering that more layers equals more processing overhead, so if you can eliminate a layer without sacrificing usability, then you should do so.

This is why the advice to "make games not engines" is given. Too often, you end up with heavily-engineered layers of overly-generic software that really isn't all that useful in practical application, because the users have to do as much coding to make it specific for their game as they would if they had just built it from the ground up anyway. The abstraction layers need to provide sensible restraints upon the solution domain if they are to be of any use at all.

#1JTippetts

Posted 30 May 2013 - 06:12 PM

Huh. Message-passing is a very loose form of coupling, but it's still coupling. What happens when the semantics of your messages change? That equates to an interface change on the components listening for particular messages. What if you have a component, HealthComponent, that listens for ApplyDamage events; but then, at some point, you add an intermediary ReduceDamage component that acts as a damage shield? At that point, you have to either rewrite the semantics of ApplyDamage and add another event type, something like ApplyModifiedDamage, in the process modifying the interfaces of any components that listen for ApplyDamage. Additionally, this line...
 
zombie->GetComponent("CombatAnimationsController")->OnStateChanged.Bind(zombie->GetComponent("AnimatedModel"), AnimatedModel::ChangeAnimation);
...indicates that you are doing a tighter coupling than simple message-passing, given that the sender (CombatAnimationsController) needs to know enough about the receiver (AnimatedModel) to know that it has a ChangeAnimation method; a true message-passing system wouldn't even be that tightly coupled. It wouldn't know, nor care, exactly which method the receiver uses, if any, to respond to a particular message.

I worry that you are trying to get too flexible with your paradigm here. Every layer of software on your machine needs to abstract away the messy, intimate details of lower layers so that the higher layers that rely upon it don't have to do as much low-level work; that means that each layer should actually restrict what can be done with it in comparison to lower layers. That is the way of computer science. Imposing limitations, setting requirements, harnessing the generic power of the underlying hardware and turning it toward specialized purposes, is the very heart of what we do. By definition, though, that means that by trying to give the users of your particular layer too much flexibility and power, you actually render your layer useless. What point having an infinitely flexible layer to work with, when they could just eliminate your layer and do everything on the layer beneath? Especially considering that more layers equals more processing overhead, so if you can eliminate a layer without sacrificing usability, then you should do so.

This is why the advice to "make games not engines" is given. Too often, you end up with heavily-engineered layers of overly-generic software that really isn't all that useful in practical application, because the users have to do as much coding to make it specific for their game as they would if they had just built it from the ground up anyway. The abstraction layers need to provide sensible restraints upon the solution domain if they are to be of any use at all.

PARTNERS