Nextras ORM, Contributte Event Dispatcher & Nettrine Event Manager vs ComponentEvents
- jahudka
- Member | 71
@Felix & @hrach – hi guys,
I'm the author of the ComponentEvents Nette extension, which aims to be a thin bridge between various event dispatchers and the Nette ComponentModel. I have come across a couple of issues with the aforementioned libraries of which you are authors and / or maintainers, as far as I know, and I'd like to ask if you'd be open to collaboration on fixing them.
When I say “issues”, I don't mean bugs – your libraries work exactly as advertised and expected – they're “issues” strictly from the point of view of my library & use case, and “fixing” them would most probably mean introducing some BC breaks (although those would most probably only be BC breaks on paper and wouldn't really break things for people in the wild – I'll get back to that later).
ComponentEvents background
ComponentEvents basically scans the DI container for presenters and then
statically analyses the component tree of each presenter using the
createComponent<name>()
pattern. Then it looks at components
which implement certain interesting interfaces and uses that information to
construct a relay service, which takes care of subscribing to events that
components of the current presenter wish to subscribe to, and forwards all of
these events to the relevant components, creating them automatically in the
process. Repo here, if
you're interested.
Contributte Event Dispatcher
Contributte Event Dispatcher automatically subscribes all services
in the DIC which implement the Symfony EventSubscriberInterface
.
The issue here is that it might also be useful to have presenters which
implement that interface, but then all presenters which subscribe to a
particular event would be created when that event is emitted, regardless of
which is the current presenter (or if there even is one). That's probably
something the user doesn't want. Would it be possible to add an option to the
Contributte Event Dispatcher DI extension which would allow the user to disable
automatic registration of specific classes / interfaces? That way the user could
simply say they don't want to autoregister any class which implements
IPresenter
(or better yet, Component Events could do it
automatically if present).
Nettrine Event Manager
Here the issue is that Doctrine's EventSubscriber
interface
defines the getSubscribedEvents()
method as an instance
method, meaning it cannot be called statically. Component Events hacks around
this by creating an instance of the subscriber without calling the constructor,
but the call to getSubscribedEvents()
can obviously still fail if
the method tries to touch something that was supposed to be initialised in the
constructor. It's probably a non-issue, because most of the time people just
return a static array of events to subscribe, so it probably won't break too
often (and it's explained in detail in the ComponentEvents readme) – but
still – do you see this as something that needs attention? Should the
Component Events library for example define its own interface? Or is there any
other solution that would be nice & clean?
Nextras ORM
The contributte/nextras-orm-events
package is also
Felix's I think, but since Nextras ORM itself is hrach's brainchild
I figured your opinion is just as relevant here. The “issue” here is that
the automatic registration of event listeners expects the listeners to be
registered as services in the DIC, which components are not (or maybe people do
that? idk.. I use the autoimplemented factories for components anyway, so the
components themselves are not in the DIC, ymmv). Even if they were, it'd still
create the same problem as described for presenters with Contributte Event
Dispatcher. Currently ComponentEvents gets around this by transferring the
annotations from the entity to the listener, and changing the value of the
annotation to describe the subscribed entities instead of the subscribing
listeners. It's a relatively small change for the user, but it's still
something they need to do differently than they're used to in order to get
Component Events to work. What do you think? Is this worth the time to
investigate a different approach, or is it a non-issue?
Conclusion
All three event dispatchers have a canonical way of registering subscribers that can be found in the DIC. Subscribers outside the DIC break things to various extents, from silently not being subscribed to screaming terror during DIC build. Ideally I'd like Component Events to allow the user to use the same canonical method of registering event subscribers for presenters and / or components as they use for regular services. What do you guys think?
- jahudka
- Member | 71
Oh, about the BC breaks – I was mostly thinking about all three of the libraries possibly automatically registering presenters as event subscribers – I think the libraries shouldn't do that (or at least that there should be a way of turning it off), but I don't think it'd be a huge BC break (in the sense of things actually breaking) if they stopped, because I don't think people usually have presenters that are event subscribers – exactly for the reason described in the “Contributte Event Dispatcher” section of the previous post – because without additional logic it will probably do more than people want to (and not in a good way).
- hrach
- Member | 1838
Personally, I don't use these events somehow extensively so I have no real experience / need for these event system. As so, Orm itself tries to expose the bare abstract minimum and let you choose your implementation – to allow various bridges and implementations. The only events that should be possible to get subscribe to are in Presenter or Model. Not the Entity events. That's probably all what I can say on this topic.