http://www.perlmonks.org?node_id=358104


in reply to Event based programming: Callbacks or "Interfaces"?

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