> The typical use case for ContainerInterface is to allow a consumer (like a router) to be "container agnostic".
I completely agree. I can't think of a use case where a router would depend on having either shared instances or exclusive instances of a controller, so I'll change this example a little. Hopefully this answers @Matthieu's question too. Let's say I have a framework component (and ORM, maybe) that triggers events (to log queries, maybe). This part of my framework fetches an event dispatcher (let's say, symfony's) from the registry, and it HAS to be a shared entry (otherwise, I'll just dispatch an event on a new instance that has no listeners). Now, my consumer, the ORM, is completely container agnostic. It only works, however, with SOME specific implementations (that ALWAYS return shared instances), and fails on SOME others (that ALLOWS for factories). I don't know (and can't control) how the entries were set, because I deferred this wiring to the application realm, by design. I don't know (and can't control) which container this is. If I can't guarantee it will work with ANY PSR-11 implementation, I cannot depend on the contract (PSR-11) - I'll have to depend of an implementation, which is bad. The only instances where I could depend on a 100% generic PSR-11 container is when I don't care at all if the service being retrieved is exclusive or shared. And there only needs to be ONE place where I need a specific kind of instance, and my entire framework will depend on a specific implementation. The event dispatcher service is one example where I need a shared instance -- the ORM could be another. I don't want new connections being opened, I don't want two separate units of work with two different in-memory caches. If I fetch my ORM twice from the container, I expect to be given the same instance, not two different separate instances. If I fetch it twice from separate consumers, I still expect to be given the same instance. Now, I'll reiterate that I understand strengthening the SHOULD to a MUST would greatly hinder this PSR's adoption. I just want to know if you guys understand my point and if you guys still disagree that this is an issue, and why. I don't know if I'm failing to see it, but as far as I can think about it, not knowing what kind of instance the container will yield would also greatly restrict the possible uses and hinder its adoption -- and I'm not even talking about things out of scope here, because I'm failing to see its usefulness even for consumer-only frameworks, like shown on the previous examples. Em quarta-feira, 2 de novembro de 2016 15:45:49 UTC-2, David Négrier escreveu: > > This is a continuation from the discussion about whether PSR-11 containers > should always return the same instance. > See https://groups.google.com/forum/#!topic/php-fig/L8rDUwRFsOU for the > beginning of the discussion. > > <TL;DR;> I believe that we should keep the SHOULD word in place because it > does not hurt in practice and because we can require a container to always > return the same instance in the yet to come PSR that will define how we put > things into a container (see container-interop/service-provider > <https://github.com/container-interop/service-provider/> for a proposal). > On the other hand, requiring the container to return always the same value > would make PSR-11 de-facto incompatible with most containers out there (so > should be avoided). However, I think we definitely need to make > improvements on the wording that is clumsy (see end of the message). > </TL;DR;> > > Currently, the spec says: > > > *Two successive calls to get with the same identifier SHOULD return the > same value. However, depending on the implementor design > and/or user configuration, different values might be returned, > so user SHOULD NOT rely on getting the same value on 2 successive calls. * > > Hari, Larry, Pedro are asking if we could strengthen the SHOULD to a MUST > (as in: *Two successive calls to get with the same identifier MUST return > the same value*). > > For instance, Larry says: > > > I would prefer to have get() defined to always return the same object > (lazy loaded or otherwise, not relevant here), as that is the typical case, > and another method added (either on the same interface or a separate one, I > am flexible) to handle the factory use case. That way I know the behavior > of each object I get back, specifically in relation to whether I have a > private copy or not. > > First of all, let me say if I was starting from a blank slate, I would > definitely agree with you and put a MUST here. But we are not starting from > a blank slate and many containers out there offer the possibility to create > new services each time you call "get". For instance Pimple (with the > factory method), or Symfony (with the "shared" option: > http://symfony.com/doc/current/service_container/shared.html) > I definitely want Pimple and Symfony in PSR-11 (or at least I want to be > able to create an adapter for those) and putting a "MUST" in the > requirements makes this impossible. So if we decide to force containers to > always return the same value, we'd better have a very good reason to do so. > > Now, what is the real impact of this? > > You all seem to imply that if we don't put a "MUST" here, then we cannot > "trust" the container to give us a usable instance. The container might be > "vicious" and decide to fool its user by giving him a new instance while > the user was expecting the same instance. But this is not how it works. The > typical use case for ContainerInterface is to allow a consumer (like a > router) to be "container agnostic". As a user, I can decide to plug any > container to a given router. The router will then be able to fetch the > correct controller (or the correct action if you do ADR) based on the > controller name. In this scenario, the user is the one in charge of > configuring the container (and putting the controller in the container). If > the user decides that he wants to use a container that can act as a factory > and that he wants to configure some services that are created on each > request, it is his responsibility. Keep in mind that since we do not > standardize how to put things in the container, it has to be the user > responsibility to configure his container. > > So saying that a container MUST return always the same instance is > premature. When we will start to standardize how to put things in a > container, then we can define that configured instances MUST be the same. > But we can do this in the next PSR (the one that defines how to put things > into a container) and not in this one. > > > Now, even if I'm really convinced that we should keep the "SHOULD" in > place, I understand from the numerous comments that the way the spec is > written is clumsy (or rather worrisome). > > Why did I propose this sentence in the first place? I was thinking that a > "CompositeContainer" could try to cache in an array the list of services > already fetched from its children. This is something you can do if you know > the children containers will always return the same instance but that you > cannot do if you don't know if the container will return the same or a new > instance. So really, the "SHOULD" prevents us to write composite containers > that "cache" the result from children. This is actually not a very big > deal, as composite containers are very seldomly used. What I was trying to > say here was: "Hey, don't cache the services returned by a container, it > might return a new instance on the next call". I proposed this wording 2 > years ago in container-interop. In hindsight, this is certainly too > specific to be part of a PSR. > > I see 3 possible solutions to replace this: > > *Solution 1*: > Let's completely drop the 2 sentences => PSR-11 does not address whether a > container should return the same instance or not (this is something we can > deal with when we define how to put things into a container) > > *Solution 2*: > Let's only keep the first sentence: *Two successive calls to get with the > same identifier SHOULD return the same value.* > > *Solution 3*: > Let's rewrite the second sentence: *Two successive calls to get with the > same identifier SHOULD return the same value. A container MAY offer the > possibility to return a new value for some identifiers if the user > configured it accordingly.* > (The wording of solution 3 should be improved but you get the idea) > > @larry, @hari, @pedro: do you favor one of those solutions or do you still > think we should use a "MUST" in the spec? > @matthieu, @mathew: any preference regarding the solutions proposed above? > > We should also try to ping more container authors to get their advice on > this issue. I'd be interested in knowing what Fabien Potencier or Taylor > Otwell think about this. > > ++ > David > -- You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/a8160704-7c68-4d33-bfe5-e925d43ead93%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
