Quantcast

Similar interface for shared events

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Similar interface for shared events

Gregory
Hi Matthew,


I wonder if you would consider making both EventManagerInterface and
SharedEventManagerInterface interfaces similar, e.g


EventManagerInterface::attach($event, $callback = null, $priority = 1);

and

SharedEventManagerInterface::attach(array($id, $event), $callback,
$priority = 1);


For the shared manager interface it suggests that nothing has to be
returned whereas the standard Event Manager Interface which generates
the CallbackHandler is expected to be returned.


Another example would be


EventManagerInterface::detach($listener);

and

SharedEventManagerInterface::detach(CallbackHandler $listener);


If the Shared Event Manager returned the CallbackHandler like the
Standard Event Manager does, then the expectation and implementation
would be the same?

Otherwise I think I would like to see an Event Manager that can pull
event listeners (or aggregates) from a service locator based on the
event 'name' being the service listener alias, by default in ZF2?


Regards,


Greg
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Similar interface for shared events

weierophinney
Administrator
-- Greg <[hidden email]> wrote
(on Saturday, 18 August 2012, 12:31 AM -0500):

> I wonder if you would consider making both EventManagerInterface and
> SharedEventManagerInterface interfaces similar, e.g
>
>
> EventManagerInterface::attach($event, $callback = null, $priority = 1);
>
> and
>
> SharedEventManagerInterface::attach(array($id, $event), $callback,
> $priority = 1);

No.

Documenting array arguments is hard, and validating them introduces a
lot of complexity. Having an explicit argument for the identifier is
necessary here so that (a) it's self-documenting, (b) it's
self-validating, and (c) it ensures differentiation between regular EM
and SEM usage -- this latter helps you identify errors easier (missing
arguments when using the SEM).

> For the shared manager interface it suggests that nothing has to be
> returned whereas the standard Event Manager Interface which generates
> the CallbackHandler is expected to be returned.

Please submit a pull request changing the return value of attach() in
the SEM, then. The actual implementation _does_ return a
CallbackHandler instance, which means it's simply a small documentation
issue in the interface.

> Another example would be
>
> EventManagerInterface::detach($listener);
>
> and
>
> SharedEventManagerInterface::detach(CallbackHandler $listener);
>
>
> If the Shared Event Manager returned the CallbackHandler like the
> Standard Event Manager does, then the expectation and implementation
> would be the same?

It's not, though. The CallbackHandler does not store the identifier, and
should not, as it can be attached separately to multiple events and
identifiers. As such, the signature on the SEM requires having an
identifier -- and, again, this helps you with contextual debugging.

> Otherwise I think I would like to see an Event Manager that can pull
> event listeners (or aggregates) from a service locator based on the
> event 'name' being the service listener alias, by default in ZF2?

Sorry, don't quite understand what you're requesting. Can you show me
some pseudo-code indicating what you'd like to do?

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Similar interface for shared events

Gregory
On Mon, Aug 20, 2012 at 9:33 AM, Matthew Weier O'Phinney
<[hidden email]> wrote:
> Documenting array arguments is hard, and validating them introduces a
> lot of complexity. Having an explicit argument for the identifier is
> necessary here so that (a) it's self-documenting, (b) it's
> self-validating, and (c) it ensures differentiation between regular EM
> and SEM usage -- this latter helps you identify errors easier (missing
> arguments when using the SEM).

I agree explicit is always better. I have previously asked considering
moving the identifier to the end of the method argument list.

In regards to differentiation between a regular EM and an SEM, that's
where I cannot change the implementation of the SEM because of its
Interface.

What if I do want to emulate a regular EM as an SEM? You're telling me it can't.

I must be the only one it seems to just want a simple interface that
would require little to no explanation.

Anyhow...

>
> It's not, though. The CallbackHandler does not store the identifier, and
> should not, as it can be attached separately to multiple events and
> identifiers. As such, the signature on the SEM requires having an
> identifier -- and, again, this helps you with contextual debugging.

I apologize if I'm just an idiot, especially as I'm stalling from
running the code, however:

$listeners[] = $this->identifiers[$id]->attach($event, $callback, $priority)

For each identifier a new CallbackHandler is being created and
assigned to a particular identifier.

Couldn't spl_object_hash of this new CallbackHandler could be used to
determine which identifier it was attached to?


>
>> Otherwise I think I would like to see an Event Manager that can pull
>> event listeners (or aggregates) from a service locator based on the
>> event 'name' being the service listener alias, by default in ZF2?
>
> Sorry, don't quite understand what you're requesting. Can you show me
> some pseudo-code indicating what you'd like to do?


$em->trigger('member.create');

This in effect could replace a concrete service method entirely. All
the default listeners would be pulled from the service locator config.

For example

public function bootstrap()
    {
        $serviceManager = $this->serviceManager;
        $events         = $this->getEventManager();

        //$events->attach($serviceManager->get('RouteListener'));
        //$events->attach($serviceManager->get('DispatchListener'));
        //$events->attach($serviceManager->get('ViewManager'));

        // Setup MVC Event
        $this->event = $event  = new MvcEvent();
        $event->setTarget($this);
        $event->setApplication($this)
              ->setRequest($this->getRequest())
              ->setResponse($this->getResponse())
              ->setRouter($serviceManager->get('Router'));

        // Trigger bootstrap events
        $events->trigger(MvcEvent::EVENT_BOOTSTRAP, $event);
        return $this;
    }


E.g

$em = $this->getEventManager() //whatever this means.
$em->trigger('mvc.bootstrap', $event);

The Event Manager will pull all the listeners for 'mvc.bootstrap' and
trigger them. There would be no need to attachDefaultListeners(), and
it would be easy to add, remove or manage their priority via
configuration files and the EM would not need to be pre-initialized in
order to do so?

Basically I might like to have service object that with a concrete
method that would just trigger the event:

MemberService::createMember($member)
{
   $em = $this->getEventManager(); //This is a shared event manager..
because it means less boiler plate code, e.g setEventManager +
identifiers.
   $em->trigger('member.create', $member);
}


Otherwise, its seems, you're forcing us to worry about identifiers,
when for the most part I don't want or need to (and others will
definitely not care), and really forcing one particular type of
implementation of a Shared Manager - Why couldn't a regular EM be used
as an SEM and let the developer have the opportunity to handle their
own implementation for integration with the ServiceManager (unless its
in Zend by default)?


--
Greg
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Similar interface for shared events

weierophinney
Administrator
-- Greg <[hidden email]> wrote
(on Monday, 20 August 2012, 01:39 PM -0500):

> On Mon, Aug 20, 2012 at 9:33 AM, Matthew Weier O'Phinney
> <[hidden email]> wrote:
> > Documenting array arguments is hard, and validating them introduces a
> > lot of complexity. Having an explicit argument for the identifier is
> > necessary here so that (a) it's self-documenting, (b) it's
> > self-validating, and (c) it ensures differentiation between regular EM
> > and SEM usage -- this latter helps you identify errors easier (missing
> > arguments when using the SEM).
>
> I agree explicit is always better. I have previously asked considering
> moving the identifier to the end of the method argument list.
>
> In regards to differentiation between a regular EM and an SEM, that's
> where I cannot change the implementation of the SEM because of its
> Interface.
>
> What if I do want to emulate a regular EM as an SEM? You're telling me it can't.
>
> I must be the only one it seems to just want a simple interface that
> would require little to no explanation.
>
> Anyhow...

I disagree with the assertion that "simpler" == "better" in this case.
There's a reason they are different, and it's because they do different
things. The SEM does not trigger events at all, it simply collects
listeners.

> > It's not, though. The CallbackHandler does not store the identifier, and
> > should not, as it can be attached separately to multiple events and
> > identifiers. As such, the signature on the SEM requires having an
> > identifier -- and, again, this helps you with contextual debugging.
>
> I apologize if I'm just an idiot, especially as I'm stalling from
> running the code, however:
>
> $listeners[] = $this->identifiers[$id]->attach($event, $callback, $priority)
>
> For each identifier a new CallbackHandler is being created and
> assigned to a particular identifier.
>
> Couldn't spl_object_hash of this new CallbackHandler could be used to
> determine which identifier it was attached to?

Using the identifier makes the operation faster, because internally,
the listeners are stored in separate objects based on identifier; this
means that instead of having to loop through the entire set of shared
listeners, we only do a subset. (This same code is also used to find the
listeners for a given identifier + event in the EM instances -- where
performance is even more critical!)


I'll address the service locator use case separately.

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Similar interface for shared events

Gregory
On Mon, Aug 20, 2012 at 4:47 PM, Matthew Weier O'Phinney
<[hidden email]> wrote:
> I disagree with the assertion that "simpler" == "better" in this case.


I understand that, but my interpretation here is that the advanced
case can and should be optional. However, this discussion could become
somewhat mute if the EMs pull from the ServiceLocator instead of the
SEM?


Lets say a new service component needs to be created, the developer
now has to learn and remember how to instantiate the identifiers for
it. That's a PITA, and per my previous threads is potentially
redundant since the identifiers can be determined from the
target/source of the event, i.e. $this.

Now I'd like to register a listener for an event of that component. So
I get the SEM and now need to specify the identifier, typically some
form of namespaced identifier.

I then refactor the new component and its identifier changes due to a
change in namespace. This means that wherever else was targeting that
identifier now needs to be updated - unless we start getting messy and
try to support BC.

Whereas if I wanted to have the choice to just work with distinct
event names, I would not have to update all those places via the SEM -
unless those listeners are targeting specific sources (but these would
be rare situations I'm imagining). Here by default the event names
would be registered to listen to all sources for a specific event
name. I think the point here, is "That is how I would like my
application code to work" - I should have this choice in simple and
clean fashion.

I can't even try this, because of the Interface of the SEM. ZF has
automatically reserved the keywords EventManager, ShareEventManager.

If the EMs can work with ServceLocator, I'd suggest that it should
replace the current usage of the SEM. This would allow the end user to
devise their own SEM should they not wish to use the suggested ZF2 SEM
- again the current SEM Interface is causing me not to be able even
try to implement a different solution.

I can't even reuse a single instance of an EventManager via the
service locator, e.g. $serviceLocator->get('EventManager'). This is in
itself is another WTF that someone else is going to have to deal with
and keep reminding about. And if the SharedEventManager can't trigger
events, again that is another WTF that would need reminding about.

There are enough problems as it is, such as remembering to escape output etc...


> I'll address the service locator use case separately.

I'm looking forward to that, and wonder if somehow the identifiers
could be shifted into the config too, i.e the source identifier for an
event name is specified in the config (I'm not overly happy about
that, but it would fit in with the current schema).


--
Greg
Loading...