8000 [DI] Reintroduce !service_locator in favor of !iterator by ro0NL · Pull Request #23542 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DI] Reintroduce !service_locator in favor of !iterator #23542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

[DI] Reintroduce !service_locator in favor of !iterator #23542

wants to merge 1 commit into from

Conversation

ro0NL
Copy link
Contributor
@ro0NL ro0NL commented Jul 16, 2017
Q A
Branch? 3.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? should be
Fixed tickets #...
License MIT
Doc PR symfony/symfony-docs#...

Basically merges Di\Arg\RewindableGenerator and Di\ServiceLocator into one. Introducing an internal god object that we can leverage to satisfy various typehints (think array, iterable, ContainerInterface). All lazy by default (well not array, we'd call iterator_to_array beforehand).

See #22200 (comment) for more info.

i dont understand why we favor

!service { arguments: { k: '@ref' }, tags: [container.service_loc] }

over (simply)

!service_locator { k: '@ref' }
!service_locator [ '@ref' ] # keys are arbitrary

What !iterator does actually

Thoughts?

@nicolas-grekas
Copy link
Member

I think the reason is that we prefer explicit, which means favouring implementing ServiceSubscriberInterface and the corresponding container.service_subscriber tag.
Helping people write bad opaque service locators is not a good idea to me.

@ro0NL
Copy link
Contributor Author
ro0NL commented Jul 16, 2017

Well i think you still could write specialized service locators by decorating one, you get from config.

My\ServiceLocator: { !service_locator { 'k': '@ref' } }

I find this easier to follow as current container.* events tbh =/

@nicolas-grekas
Copy link
Member

I'm not sure we should follow this path. But let's say yes, I think we should make ServiceLocator implement IteratorAggregate, vs RewindableGenerator implement PSR 11. We should also ensure that factory closures are dumped only once. We could also have all tags generate code using this enhanced ServiceLocator, thus make PhpDumper simpler, and deprecate RewindableGenerator and maybe also IteratorArgument, while keeping the same set of tags + the one you're pushing for.
But I don't want you to loose your time, so this is just a thought, not really a proposal :)

@ro0NL
Copy link
Contributor Author
ro0NL commented Jul 16, 2017

I dont wanna push.. :) just having thoughts if we got this right. I tend to think we should go with plain verbose config; "give me this, here" instead of event based approach.

I think we should make ServiceLocator implement IteratorAggregate, vs RewindableGenerator implement PSR 11.

As Arg\Rewindable.. is internal, idea was to rename it to Arg\ServiceLocator. And rename Arg\IteratorArg to Arg\ServiceLocatorArg, including the corresponding tag.

while keeping the same set of tags

For cosmetic purposes that seems fine indeed.

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Jul 17, 2017
@nicolas-grekas
Copy link
Member

"give me this, here" instead of event based approach

this sentence makes me think there is some misunderstanding somewhere: ServiceSubscriberInterface has nothing to do with events, and everything to do with being explicit, at the class-consumer level (even better than the config level).

make ServiceLocator implement IteratorAggregate

I revert this idea, asking for an iterator should give you an iterator, not dual PSR11/iterable object :)
It is still true that the PhpDumper could dump a bit less optimized code and be simplified by sharing the dumping logic for iterators/service-factories. But since this does not serve any purpose yet, that's not needed.

@ro0NL
Copy link
Contributor Author
ro0NL commented Jul 17, 2017

at the class-consumer level (even better than the config level)

To me this is PHP config. I see it's charming to have this at the class level, but your allowed to violate it anyway (right?) using container.service_subscriber.

I will play with container.* tags bit more this week, to convince myself it's better than straightforward config 👍

asking for an iterator should give you an iterator, not dual PSR11/iterable object :)

But do we care? User ask for iterable, we give an iterable. User asks for PSR container, we give on. The user should not have to rely on the implementation we provide, but only care about public API he needs. But maybe im being too pragmatic here :)

@nicolas-grekas
Copy link
Member
nicolas-grekas commented Jul 17, 2017

We care because people will notice, then do mistake of asking for an iterator and using it as psr11. That's a trap.

On the implementation level, I think we forgot something: thanks to IGNORE_ON_INVALID, iterators are allowed to skip values. That looks like the technical justification for the current clear split between both.

All in all, maybe your tag is worth it and we should continue considering it, but implementation wise, I'm getting more and more convinced that the current code is the correct one.

@ro0NL
Copy link
Contributor Author
ro0NL commented Jul 17, 2017

then do mistake of asking for an iterator and using it as psr11. That's a trap.

And a sign of bad typehints, but indeed, it may be to flexible after all.

thanks to IGNORE_ON_INVALID, iterators are allowed to skip values. That looks like the technical justification for the current clear split between both.

Hm good point! Note there's no such thing as get() returning null in a PSR context, this PR would simply throw not found; not sure how the current service locator deals with that actually :)

I guess we can keep it separated, nevertheless you can keep use !iterator as a map/service locator, as it preserves keys. Thats whats made me think we could combine it into a one-size-fits-all solution.

So, basically;

  • keep !iterator > IteratorArgument > RewindableGenerator (satisfies iterable)
  • add !service_locator > ServiceLocatorArgument > ServiceLocator (satisfies ContainerInterface)
  • add !service_closure > ServiceClosureArgument > Closure (satisfies callable)
  • all container.* tags are maintained, still skeptical though :)
  • add !tagged-services > IteratorArgument (i guess then)

Although it may help core things, i really intended this as a (imo. priceless) end-user feature. Hope you can appreciate that.

@ro0NL
Copy link
Contributor Author
ro0NL commented Jul 18, 2017

Ok. im closing. Current features work fine individually, there's no real reason to combine. Though i still think it's a sane/pragmatic thing to do.

Also we already have !service_locator in disguise using container.service_locator tag. Thats fine i guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0