Thread overview
API question: Delagates/FPs or Interface?
Apr 17, 2007
Robert Fraser
Apr 17, 2007
Dan
Apr 17, 2007
0ffh
Apr 17, 2007
Daniel Keep
April 17, 2007
Hi all,

I'm working on a new NAT/firewall traversal library in D right now, and I have a question for you all: since D has enough expressive power to expose both function pointers and interfaces, which would you prefer for a set of "callback" functions. In particular, the library allows a client to start establishing a connection in a separate thread, and when the state of the connection changes, a function is called to inform the client.

I had two possible solutions in mind:
1. Create an interface with the required methods (such as onFailedState, onErrorState, onSuccessState, etc.) specified. The library takes a pointer to an implementing object and calls the methods through that.
2. Accept a set of function pointers or delegates (I'll overload the methods so either is acceptable), and call the functions through that. One advantage of this is that a single callback function is easily interchangeable without having to re-implement the entire interface, and it promotes code reuse because a client might want to implement, for example, only a single onFailedState method, but have a different onSuccessState for different types of connections.

If you think the first option would be better for something like this, there are a couple of other places with a single callback function is needed (for example, to deal with an incoming connection invitation) that don't fit into a set... Should these be interfaces as well?

Thanks for whatever input you have,
All the best,
Robert Fraser
April 17, 2007
Hi Robert,

I would write an array of structs such that the function probing/handling the state change already has the appropriate struct in hand, and merely looks up the callback, and also has the name of the callback on hand (such as "onErrorState" as a char[])

Any other relevant metadata may also be attached; according to performance refactoring and such considerations.

Does this help, should I rephrase it, or does that not work?

Sincerely,
Dan

~~~~~~~~
Robert Fraser Wrote:
> Hi all,
> 
> I'm working on a new NAT/firewall traversal library in D right now, and I have a question for you all: since D has enough expressive power to expose both function pointers and interfaces, which would you prefer for a set of "callback" functions. In particular, the library allows a client to start establishing a connection in a separate thread, and when the state of the connection changes, a function is called to inform the client.
> 
> I had two possible solutions in mind:
> 1. Create an interface with the required methods (such as onFailedState, onErrorState, onSuccessState, etc.) specified. The library takes a pointer to an implementing object and calls the methods through that.
> 2. Accept a set of function pointers or delegates (I'll overload the methods so either is acceptable), and call the functions through that. One advantage of this is that a single callback function is easily interchangeable without having to re-implement the entire interface, and it promotes code reuse because a client might want to implement, for example, only a single onFailedState method, but have a different onSuccessState for different types of connections.
> 
> If you think the first option would be better for something like this, there are a couple of other places with a single callback function is needed (for example, to deal with an incoming connection invitation) that don't fit into a set... Should these be interfaces as well?
> 
> Thanks for whatever input you have,
> All the best,
> Robert Fraser

April 17, 2007
Hi, Robert!

Robert Fraser wrote:
> I'm working on a new NAT/firewall traversal library in D right now,
> [...]

Personally, I wouldn't consider it good style to force the library
user (or yourself) into the object-oriented metaphor to accomplish
a task where there is no clear advantage in doing so.
Consequently, if there is no clear advantage, /just say no/... ;-)

Happy hacking,

  0ffh
April 17, 2007
"Robert Fraser" <fraserofthenight@gmail.com> wrote in message news:f034me$u2v$1@digitalmars.com...

> Thanks for whatever input you have,
> All the best,
> Robert Fraser

I like the delegate method better.  Implementing interfaces seems too "I'm Java and I don't have any expressive capabilities" to me.


April 17, 2007

Robert Fraser wrote:
> Hi all,
> 
> I'm working on a new NAT/firewall traversal library in D right now, and I have a question for you all: since D has enough expressive power to expose both function pointers and interfaces, which would you prefer for a set of "callback" functions. In particular, the library allows a client to start establishing a connection in a separate thread, and when the state of the connection changes, a function is called to inform the client.
> 
> I had two possible solutions in mind:
> 1. Create an interface with the required methods (such as onFailedState, onErrorState, onSuccessState, etc.) specified. The library takes a pointer to an implementing object and calls the methods through that.
> 2. Accept a set of function pointers or delegates (I'll overload the methods so either is acceptable), and call the functions through that. One advantage of this is that a single callback function is easily interchangeable without having to re-implement the entire interface, and it promotes code reuse because a client might want to implement, for example, only a single onFailedState method, but have a different onSuccessState for different types of connections.
> 
> If you think the first option would be better for something like this, there are a couple of other places with a single callback function is needed (for example, to deal with an incoming connection invitation) that don't fit into a set... Should these be interfaces as well?
> 
> Thanks for whatever input you have,
> All the best,
> Robert Fraser

My personal feelings would be to use delegate callbacks for singular things, and interfaces for logically connected things.

For example, SAX works well using interfaces because if you're going to
have a "startElement" callback, odds are you're going to at least use an
"endElement" and "characters" callback as well.  Since these are
logically related to each other, you use an interface to keep them together.

On the other hand, if you've got a window with things like onClick, onKeyPress, onLoseFocus, they're not really related to one another. Using one of them doesn't really mean you'll use any of the others.  In that case, use delegates and let the user attach a callback to them individually.

Finally, I'd be inclined to err on the side of delegates; they're slightly more flexible, and if you find you're always using a particular set of delegates, you can always write a base class that handles registering the delegates for you.

Anyway, my AU$0.02 :)

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/