Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Event based programming: Callbacks or "Interfaces"?

by BUU (Prior)
on Jun 01, 2004 at 05:26 UTC ( #357935=perlmeditation: print w/ replies, xml ) Need Help??

I find myself writing something like an event driven frame work, and I was pondering the various ways in which I've seen it done. It seemed to me, that the two main ways are "callbacks" and "interfaces".

Callbacks, of course, are obvious in what they do and how they work, and it's how most GUI Toolkits, such as tk, do things. You call some function and pass a coderef to it. Example:
sub called { print "You pressed a button!"; } my $button = new Button( name=>'foo', callback=>\&called );
The coderef passed to the constructor is derefenced when ever it's need to, and the call back is called.

The second way, which I've called "interface", although perhaps "inheritance" or some other word would better describe it, is how, for example, WxWindows does things. In this case, you don't call a function and pass a coderef to it, you simply implement a specific "interface" in your base class and then the other code uses this interface to interact with you. If that wasn't particularly clear, perhaps this example will help:
class MyButton; use Base 'Button'; sub on_click { print "You pressed a button"; } package main; my $button = new MyButton();
In this case you inherit the "other" methods, constructor, destructor, etc from a base class, then just implement the interface you wish to provide.

The pros and cons, as far as I can tell, is mostly that callbacks allow you to pass annonymous subs, or the same subref to multiple callbacks, but both of those are fairly minor pros, so this is what I ask you: Are there any other pros/cons I missed? Which do you prefer using? Why?

Comment on Event based programming: Callbacks or "Interfaces"?
Select or Download Code
Re: Event based programming: Callbacks or "Interfaces"?
by ambrus (Abbot) on Jun 01, 2004 at 06:47 UTC
    class MyButton; use Base 'Button';

    Isn't that package and base?

    package MyButton; use base 'Button';
      What can I say? You're completely right. No idea what I was thinking.
Re: Event based programming: Callbacks or "Interfaces"?
by leriksen (Curate) on Jun 01, 2004 at 06:51 UTC
    Both styles result in a function getting called, but that function is determined in different ways

    1. explicitly named
    2. resolved through a hierarchy

    I think that the flexibility afforded by the interface style is by far a more effective technique.

    An interface can change at runtime, whole new classes of behaviour can easily be brought to bear with just a few keystrokes, etc, technique much harder to achieve through static coderef's.

    +++++++++++++++++
    #!/usr/bin/perl
    use warnings;use strict;use brain;

      I detect someone who doesn't appreciate the power of closures. After Why I like functional programming, perhaps you'll appreciate better what you can accomplish with callbacks.
      I think that the flexibility afforded by the interface style is by far a more effective technique.

      IMHO (using several C++ GUI libraries), it really depends on what you have to provide to your users:

      • Your code offers GUI services for end-user application,
      • You're about to make a complete framework, hiding implementation details.

      Interface based framework implies exposing the whole framework to the end user application which is tied to it. This also could be problematic with portability requirements.

      Callback driven framework enables you to have a centralized event handling and to use finite-state machine if required (i.e. the same sub handles all the events of a form and its widgets).

      The object definition features of the choosen implementation language is also a constraint. Very often, using hierarchy of objects implies needing runtime type information, introspection, persistence,... Things and behaviours which are not always available natively nor easy to implement (I'm thinking of C++ and more generally of all compiled languages).

      Anyway, the two systems can co-exist... :-)

      HTH, Dominique
      An interface can change at runtime, whole new classes of behaviour can easily be brought to bear with just a few keystrokes, etc, technique much harder to achieve through static coderef's.

      I don't think this is true myself. With a callback based model it's trivial to produce one-off callbacks without having to create a whole separate class that may be overkill. Closures and anonymous subroutines give you a heck of flexibility at runtime.

      Personally I would use a class based approach if cutting up the domain into classes made sense (do you have common behaviour where inheritance would make sense, are you creating multiple instantiations of the same sort of objects, etc.) Otherwise callbacks would probably be best.

        I would use a class based approach if cutting up the domain into classes made sense (do you have common behaviour where inheritance would make sense . . . Otherwise callbacks would probably be best.

        Except that you probably won't get to choose. The decision will be forced on you by the GUI toolkit you use. I suppose you could write a glue layer to transfer between the two styles, but the added complexity may not be worth it.

        ----
        send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

(ot) Re: Event based programming: Callbacks or "Interfaces"?
by PodMaster (Abbot) on Jun 01, 2004 at 08:21 UTC
    The second way, which I've called "interface", although perhaps "inheritance" or some other word would better describe it, is how, for example, WxWindows does things.
    Getting off topic here for a second, but thats a bad example. wxWindows uses callbacks (and besides, theres nothing stopping you from subclassing a Tk::Button).

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Event based programming: Callbacks or "Interfaces"?
by tilly (Archbishop) on Jun 01, 2004 at 08:24 UTC
    Callbacks make it easier for me to abstract things out so that I have code that writes code that is run...if I choose to do things that way.

    OO interfaces might work better if I'm already organizing code in an object-oriented way. Assuming that the way that I want to organize code matches what the API is going to look for.

    My personal preference is for callbacks if the API is simple and an OO interface if it is not. But that isn't a strong preference. In fact it is a good exercise to figure out how to make a callback API turn into something that expects an OO interface. (Hint: You may have to assign to typeglobs.) Conversely you can take something that expected an OO interface and have it call methods that were passed into the constructor via callback. (Hint: Store the callbacks in the object.)

Re: Event based programming: Callbacks or "Interfaces"?
by valdez (Monsignor) on Jun 01, 2004 at 09:07 UTC

    Are you working with an infrared remote control? Well, I'm working on something similar :)

    I copied the approach used by CGI::Application: every Remote class has methods for every buttons/runmodes, but, unlike C::A, the association of a runmode to one or more buttons is made inside a configuration file.

    HTH, Valerio

Re: Event based programming: Callbacks or "Interfaces"?
by etcshadow (Priest) on Jun 01, 2004 at 14:43 UTC
    Not that this is directly in answer to your question, but...

    I'd try to avoid any kind of callback interface (unless there is a really good reason to use it). And by that I mean either an explicitly named callback (passing a coderef), or an implicitly named callback (what you are calling "Interfaces"). In pretty much any case where you are writing a callback-style interface to your code, you could be (and, imho, should be) writing an "iterator"-style interface.

    That is: instead of calling

    DoStuff({@parameters, on_event=>\&handle_event});
    Try constructing your code so that it can be used like
    my $doer = new ThingThatDoesStuff ({@parameters}); while ($doer->GetNextEvent()) { # handle event }
    Or, perhaps even better, support both kinds of interfaces (because, honestly, callbacks can be a little easier to work with if you are doing something simple, and you understand callbacks really well).

    Why does this matter? Well, imagine someone else who wants to implement something that uses your code, and, for some reason, they aren't able to implement their module with a callback-style interface. (This comes up a lot, you know... you've got to make something with an interface that was already defined by someone else.) If you wrote your code such that it could only be used with callbacks (and without any sort of ->GetNext() type of interface available to it), then it is actually impossible (I know... not a word often used in the context of perl) to build an iterator-like interface around it. (If you want to prove me wrong: show me some code that actually uses File::Find, but presents an iterator interface.)

    However, it is trivial to implement a callback-style interface around an iterator (based loosely on the previous, silly example):

    package ThingWithCallbacks; use ThingAsIterator; sub DoThing { my ($params) = @_; my $callback = $params->{callback}; my $doer = new ThingAsIterator ({@parameters}); while (my $event = $doer->GetNextEvent()) { &$callback($event); } }
    And that's all there is to it. So, you see... make an iterator interface, so that you don't make the decision of what interface everyone else has to use.
    ------------ :Wq Not an editor command: Wq
      I understand completely where you are coming from, I read the original discussion about hating on File::Find, but to be honest, I have no freaking idea how I'm supposed to make an iterator interface for this thing.

      The code in question is almost certainly going to respond to only one event at a time. The code will probably be eval'd once for each event needful, so it'll never have any access to the "next event". I suppose in rare cases it might handle 2 or 3 events, but I doubt it. This is primarily for security purposes as the code handling the event is going to be untrusted, so I don't want it hanging around for very long.
        Fair enough... which is why I qualified my statement as "unless there is a really good reason not to".

        But just to throw in one parting jibe: untrusted code is another reason to avoid callbacks. :-)

        Also, for the record: I don't hate File::Find, I just wish that the writers had made a different interface for it. One of the reasons why I was probably so negative about File::Find is that I'm still stuck in 5.005, and the File::Find that came with 5.005 was really hardly any better than rolling your own. It's gotten better since then, though (in terms of performance, features, and cross-platform portability... but not in terms of code sanity or interface design).

        ------------ :Wq Not an editor command: Wq
Re: Event based programming: Callbacks or "Interfaces"?
by zby (Vicar) on Jun 02, 2004 at 09:30 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://357935]
Approved by mpolo
Front-paged by kvale
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2014-08-30 18:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (293 votes), past polls