www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - API question: Delagates/FPs or Interface?

reply Robert Fraser <fraserofthenight gmail.com> writes:
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
Apr 17 2007
next sibling parent Dan <murpsoft hotmail.com> writes:
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
Apr 17 2007
prev sibling next sibling parent 0ffh <spam frankhirsch.net> writes:
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
Apr 17 2007
prev sibling next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Hi Dan,

I'm not quite sure exactly what you mean there. Why would the struct need to
contain more than just a function pointer? Making an array of structs
containing function pointers and looking them up seems to add a needless level
of complication without really gaining anything.
Apr 17 2007
prev sibling next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Okay, cool, that's what I was thinking, too. I gues sthe real advantage of the
interface option is that a uaer knows exactly what they need to implement
without nessescarily referring to the spec.
Apr 17 2007
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Apr 17 2007
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
Apr 17 2007