Nextras ORM, Contributte Event Dispatcher & Nettrine Event Manager vs ComponentEvents

jahudka
Member | 69
+
0
-

@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 | 69
+
0
-

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 | 1819
+
0
-

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.