Thread overview
Design Question: Delegation vs. callbacks
Jun 16, 2007
Henning Hasemann
Jun 16, 2007
Jason House
Jun 17, 2007
Henning Hasemann
Jun 17, 2007
Daniel Keep
June 16, 2007
Say I have basically three classes which form my problem: Thing, Area and Animation.

A thing is something on the screen you can interact with, and area just defines a number of pixels (there are rectangular areas as well as bitmasks), an animation is something you can actually see.

Now a thing has a Position somewhere on the screen and it has an area, so you can check if it was clicked, also it will probably have an animation from wich an area can be get with the method boundingBox().

Say Area has a method isIn(x,y) which says if the coordinate is inside the area. Now I have two possibilities:

"Delegation":
  Thing's area is private but Thing has its own isIn(x,y) method
  where it substracts its own method and then delegates the call
  to area, so area doesnt have a position at all.
  Similar approach then for animation and a render() method.

  cons:
  - I cant position a plain animation on the screen without a thing or
    an other wrapper class.
  - This pattern drastically flattens structure: thing re-implements
    lot of the methods of area and animation with the delegates,
    but *does not* inherit from their possible interfaces.
    (If it would, the isIn() etc... methods would have different
    semantics: in thing isIn would accept a screen-position whereas
    in area isIn would operate on a position relative to the area)

"Callbacks":
  Everything operates with absolute screen-coordinates and area as well
  as animation have function pointers / delegates to check, what the
  position of the thing is, they belong to.

  cons:
  - the callbacks feel somewhat "magical", especially when you consider
    the bounding box stuff: the area returned by .boundingBox() would
    look up its position from the animation wheres the animation would
    look at the thing.
    It might feel weird that the .position attribute of something can
    change, just because I change a totally different thing.

What would you choose? Do you see other alternatives to solve this?

TIA
Henning






-- 
GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D  E6AB DDD6 D36D 4191 1851
June 16, 2007
Honestly, it sounds like you need to take a step back and look at the higher level design.

  Normally, I'd expect thing (or widget) to be a base class for many graphics objects.
  If you want a coherent architecture that doesn't confuse the user, I'd recommend avoiding differing types of functionality with the same function name.  Maybe it's best to rename one or both of your isIn functions?
  If position is defined to be the upper left corner of a bounding box (or some similar definition), one of two things should result:
  a. The position to change if a component has been changed.  The object has changed, so its properties changed.  The user must live with it.
  b. The containing object forces everything inside it to conform to its dimensions.  Drawing a circle that goes outside of a window shouldn't leave a mark on the desktop...

Henning Hasemann wrote:
> Say I have basically three classes which form my problem:
> Thing, Area and Animation.
> 
> A thing is something on the screen you can interact with, and area just
> defines a number of pixels (there are rectangular areas as well as
> bitmasks), an animation is something you can actually see.
> 
> Now a thing has a Position somewhere on the screen and it has an area,
> so you can check if it was clicked, also it will probably have an
> animation from wich an area can be get with the method boundingBox().
> 
> Say Area has a method isIn(x,y) which says if the coordinate is inside
> the area. Now I have two possibilities:
> 
> "Delegation":
>   Thing's area is private but Thing has its own isIn(x,y) method
>   where it substracts its own method and then delegates the call
>   to area, so area doesnt have a position at all.
>   Similar approach then for animation and a render() method.
> 
>   cons:
>   - I cant position a plain animation on the screen without a thing or
>     an other wrapper class.
>   - This pattern drastically flattens structure: thing re-implements
>     lot of the methods of area and animation with the delegates,
>     but *does not* inherit from their possible interfaces.
>     (If it would, the isIn() etc... methods would have different
>     semantics: in thing isIn would accept a screen-position whereas
>     in area isIn would operate on a position relative to the area)
> 
> "Callbacks":
>   Everything operates with absolute screen-coordinates and area as well
>   as animation have function pointers / delegates to check, what the
>   position of the thing is, they belong to.
> 
>   cons:
>   - the callbacks feel somewhat "magical", especially when you consider
>     the bounding box stuff: the area returned by .boundingBox() would
>     look up its position from the animation wheres the animation would
>     look at the thing.
>     It might feel weird that the .position attribute of something can
>     change, just because I change a totally different thing.
> 
> What would you choose? Do you see other alternatives to solve this?
> 
> TIA
> Henning
> 
> 
> 
> 
> 
> 
June 17, 2007
>    Normally, I'd expect thing (or widget) to be a base class for many
> graphics objects.

Ok, Ill give some more detail here:
My project is an engine for classical 2D adventures (like the old
LucasArts ones).
A thing is everything the player can interact with. I.e it might be
another character, or something to pick up or to push, ...

A thing needs an area to be able to receive mouse clicks, but I need areas in other places, too (for example in 'regions' when I want to trigger events as soon as the character stands at a certain place)

>    If you want a coherent architecture that doesn't confuse the user,
> I'd recommend avoiding differing types of functionality with the same
> function name.  Maybe it's best to rename one or both of your isIn
> functions?

Are you talking about something like isInRelative() and isInAbsolute()?
Sounds like a good idea for the delegate approach.

>    If position is defined to be the upper left corner of a bounding
> box (or some similar definition), one of two things should result:
>    a. The position to change if a component has been changed.  The
> object has changed, so its properties changed.  The user must live
> with it. b. The containing object forces everything inside it to
> conform to its dimensions.  Drawing a circle that goes outside of a
> window shouldn't leave a mark on the desktop...

A thing can also define its alignment relative to its position.
For example most things have their position ad middle-bottom (center of
feet) which hos some advantages when finding out the z-order of objects.

Thanks so far for your answer. It already helped me much to see the thing a bit clearer.


-- 
GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D  E6AB DDD6 D36D 4191 1851
June 17, 2007

Henning Hasemann wrote:
>>    Normally, I'd expect thing (or widget) to be a base class for many
>> graphics objects.
> 
> Ok, Ill give some more detail here:
> My project is an engine for classical 2D adventures (like the old
> LucasArts ones).
> A thing is everything the player can interact with. I.e it might be
> another character, or something to pick up or to push, ...
> 
> A thing needs an area to be able to receive mouse clicks, but I need areas in other places, too (for example in 'regions' when I want to trigger events as soon as the character stands at a certain place)

I'd be tempted to have an IHasArea interface which both Thing and Area implement.  In the case of Thing, it would pass the call on to an internal Area object.  That, or you could always expose the Area object (although that's a bit risky until we get D2.0 and const).

	-- Daniel