iarna / MooseX-Event

A Node.js style event Role for Moose
https://metacpan.org/module/MooseX::Event
2 stars 2 forks source link

From RT: Additional Documentation Requested #1

Open iarna opened 12 years ago

iarna commented 12 years ago

https://rt.cpan.org/Ticket/Display.html?id=73922

rod.taylor writes: I've been using the module across multiple objects with some success but getting there wasn't entirely obvious and is worth documenting.

A brief section showing how to wrap on subs to get your own object reference into $self and perhaps showing how to use handles to share the on/emit functions with subclasses would be useful.

Attached is an an example code snippet of what I'm doing.

Subject: k.pl

use v5.12.4;

package Foo;
use MooseX::Event;

has_events qw{one};

sub BUILD {
        my $self = shift;
        $self->on(one => \&fooFunc);
        return;
}

sub fooFunc {
        my ($self, @args) = @_;
        say "Got event 'one' in Foo";
}

package Bar;

use Moose;
use Data::Dumper;

has foopack => (is => 'rw', isa => 'Foo', handles => [qw{on emit}]);

sub BUILD {
        my $self = shift;

        # This does not give $self the expected reference. It is going to be Foo despite
        # someFunc being located in Bar package.
        #$self->on(one => \&someFunc);

        # This does work. Stripping off the $self reference passed in and replacing with the
        # local object
        $self->on(one => sub {$self->someFunc(@_)});
        return;
}

sub someFunc {
        my ($self, $emitObj, @args) = @_;

        say "Got event 'one' in Bar";
        say "Package : ". (ref $self) . " ". Data::Dumper::Dumper(\@args);

        return;
}

package main;

my $foo = Foo->new();
my $bar = Bar->new(foopack => $foo);

$foo->emit(one => 'arg');
rbt commented 12 years ago

The important piece for documentation was how to handle a subscription within Bar for items in Foo. Bar->someFunc wants the proper reference to $self. To do this the registration method needs to be:

$self->on(one => sub {$self->someFunc(@_)});

The documentation should show this mechanism in addition to "$self->on(one => &someFunc);". It seems really obvious once I figured it out but the few minutes up until that point I thought MooseX::Events was broken because $self in Bar->someFunc() was always wrong.

iarna commented 12 years ago

I find your code confusing, because it basically inverts the usual model. Normally you would never ever call emit outside of the class itself. The usual model is more like:

my $foo = SomeModule->new();
$foo->on( InterestingThingy => sub { say "Hey, an interesting thingy happened" });
$foo->do_stuff();

And then off in SomeModule::do_stuff, it calls ->emit('InterestingThingy') which then results in your event listener getting called. Eg, the example in the synopsis of MooseX::Event.

iarna commented 12 years ago

Setting up event listeners at BUILD time is unusual, but could happen if you were knitting together two event based classes. Setting them up on your own events, is almost certainly wrong.

I'll have to spend more time to understand your intent here, but when I do I'll post something that demonstrates how I would have done what you're trying to do. =)

rbt commented 12 years ago

Setting them up on your own events, is almost certainly wrong.

Yes, I'm certainly not using events for their intended purpose. A better module available now might be MooseX::Callbacks although it lacks both once() and deregister() functionality. I needed something which could register zero to many listeners to a stream of data and deregister them on the fly. POE is where I would have gone if ::Events was too slow but pleasantly, it has not been.

Basically, I have a Singleton with ::Events on it which has a number of changing objects feeding data ( via emit() ) into a number of changing objects which are listening and acting on that data.

MooseX::Events was a fairly efficient means of creating a data bus between many different very loosely coupled objects.

rbt commented 12 years ago

Hope all this helps.

Either way, thank-you for writing MooseX::Events and saving me from either writing my own similar functionality or over-engineering it with a POE system.

iarna commented 12 years ago

Ok, yes, wow, had my perspective shift reading your code there. =) It makes a lot more sense now. I'll probably write up my reply as a gist, so I can reply inline to your code. What you're doing is very interesting, but clearly there's still a bit of an impedance mismatch between MooseX::Event's intended use and what you're doing with it. I think a relatively small subclass (of MooseX::Event) might actually be able to make it clean though.