Hi David,

Thank you for taking the time to consider my proposal. While many points 
expressed by you are true, however, this is now how I see things.

The `ParentAwareContainerInterface` is a formal way of saying "this 
container can have a parent". Nothing more, nothing less. The "delegate 
feature" is simply a *pattern* that is possible as a result of that 
formalization - because now containers can form a hierarchy, which is 
impossible (reliably) without this formalized bond. In simpler words, 
lookup delegation is not a formal albeit optional feature of the *standard*, 
but rather something that is possible to implement via the standard. All 
we're doing is giving implementations the possibility of a reliable 
hierarchy. If they want to implement lookup delegation, they can now do it.

>From this point of view, the consumer of the 
`ParentAwareContainerInterface` can be any consumer wishing to access the 
hierarchy, not only a child container. For example, an implementation may 
want to print or log a string that represents a "lookup path" by giving 
each container a code. Thus, this interface is useful to any consumer that 
needs to be hierarchy-aware. Up to now, there is no concept of hierarchy in 
the standard, and the use of the interface would be to introduce that 
concept.
Also, using a "definition resolution" mechanism demonstrated in my 
implementation, one could have as a parent something that is not 
necessarily a composite container - but maybe simply another container to 
delegate lookup to. Thus, the concept of "parent" is given an even more 
precise definition as simply "something that takes precedence in service 
definition resolution". Kinda similar to how DOM events work.

With regard to the expense of parent lookup. Typical use, as I described in 
the project's readme, would involve invocation of the `get()` method on the 
topmost container, which would be the only container that the consuming 
application needs to be aware of. According to the composite container 
spec, the composite container does not perform service lookup in the 
regular sense of this word, but matches the service ID with child 
containers. Like this, caching (again, typical use) remains on the level of 
the matching container (the one that matches, i.e. contains the service 
definition). As a result, parent lookup will only be performed once per 
service - not because the parent is cached, but because the service 
referencing the parent is cached. Like this, containers remain independent 
of their parent, which is a great level of flexibility that may be 
beneficial in some scenarios. In other words, child containers may be 
potentially re-attached to other parents, without breaking the hierarchy 
mechanism. On the other hand, a DI implementation that allows simple values 
as service definition (e.g. Pimple) can have the correct values retrieved 
after the parent is switched.
It could also be possible to implement caching on the level of the root 
container, further increasing speed.

I guess, the point I am trying to make is that *everything still remains 
optional, but is now possible in the scope of the standard specification*. 
I think this is a part of what constitutes a good standard, and therefore I 
conclude that the `ParentAwareContainerInterface` is still necessary. Also, 
again in light of the above explanation, I do not believe that "root 
parent" resolution *should* necessarily be done before the child container 
is created. In my proposed approach, it remains an implementation detail 
that *can* be done this way.

Looking forward to your further comments, as well as those of other 
participants!

On Monday, October 10, 2016 at 12:48:56 PM UTC+2, David Négrier wrote:
>
>
> <https://lh3.googleusercontent.com/-MJQw2yspEUE/V_tt0Bg3xPI/AAAAAAAAB8s/Z6txSatzpM83T_v0AqUvcQXvgitUuzS1ACLcB/s1600/container_explanation.png>
>
>
>
> <https://lh3.googleusercontent.com/-MJQw2yspEUE/V_tt0Bg3xPI/AAAAAAAAB8s/Z6txSatzpM83T_v0AqUvcQXvgitUuzS1ACLcB/s1600/container_explanation.png>
>
> Hey,
>
> Ok I spent the week-end trying to think about the pros and cons of this 
> proposal.
>
> @XedinUnknown, I'm not sure I understood 100% of your proposal so I'll try 
> to rephrase it. If I'm wrong, let me know.
>
> I understand you are trying to improve the "delegate lookup feature". Your 
> goals are:
>
> - to make it "explicit" that a container is implementing the "delegate 
> lookup feature"
> - to make it possible to nest containers at an unlimited level (to be able 
> to nest a composite container in another composite container...)
>
> To do so, you propose to add a new interface named 
> ParentAwareContainerInterface 
> <https://github.com/XedinUnknown/di/blob/master/src/ParentAwareContainerInterface.php>.
>  
> This interface is exposing a single method "getParentContainer()" that 
> returns the parent container if any (i.e. the composite container 
> containing this container).
> When resolving a dependency, the container goes up the chain of parent 
> containers 
> <https://github.com/XedinUnknown/di/blob/master/src/AbstractParentAwareContainer.php#L39-L55>
>  
> until it reaches the root container. It uses the root container to look up 
> any dependency (just like in the current delegate lookup feature).
>
> Here are a few thoughts about this idea:
>
> First: who is consuming the ParentAwareContainerInterface 
> <https://github.com/XedinUnknown/di/blob/master/src/ParentAwareContainerInterface.php>?
>  
> This interface is consumed by "child" containers. If a container is a leaf 
> in the container tree (so if it is not a composite container), then there 
> is no need for it to implement the ParentAwareContainerInterface 
> <https://github.com/XedinUnknown/di/blob/master/src/ParentAwareContainerInterface.php>.
>  
> The interface is trivial to implement and is a good declaration of intent 
> (your container states it supports delegate lookup feature) but it is none 
> the less useless. This interface is only useful for composite containers 
> (so that they can also be bundled into parent composite containers).
>
> Second, each container now needs to find the root container by going up 
> the container tree. In your sample, you do this while resolving a service 
> <https://github.com/XedinUnknown/di/blob/master/src/AbstractParentAwareContainer.php#L64>.
>  
> This is a bit of a problem performance-wise because this will slow service 
> resolving (and this is a major no no for many implementors). Of course, 
> there is a simple way around that. Finding the root container could be done 
> only once, possibly in the constructor. This assumes that the parent 
> container is passed to the child container constructor (or at build time). 
> This also assumes that the parent container will never change in the life 
> of a container (this is a safe assumption). Looking at @XedingUnknown code, 
> this means that stuff like containers with mutable parents 
> <https://github.com/XedinUnknown/di/blob/master/src/ContainerWithMutableParent.php>
>  
> should be forbidden and only containers with immutable parents 
> <https://github.com/XedinUnknown/di/blob/master/src/ContainerWithImmutableParent.php>
>  
> should be allowed.
>
> If we assume that the "parent" container is always passed to containers in 
> their constructor, it means that containers MUST be constructed in the 
> order of the tree (from top to bottom).
>
>
>
> <https://lh3.googleusercontent.com/-MJQw2yspEUE/V_tt0Bg3xPI/AAAAAAAAB8s/Z6txSatzpM83T_v0AqUvcQXvgitUuzS1ACLcB/s1600/container_explanation.png>
>
>
> <https://lh3.googleusercontent.com/-MJQw2yspEUE/V_tt0Bg3xPI/AAAAAAAAB8s/Z6txSatzpM83T_v0AqUvcQXvgitUuzS1ACLcB/s1600/container_explanation.png>
>
> I made a picture so it would be more clear. If the "root container" exists 
> before "Composite A" and if "Composite A" exists before "Container 1", then 
> when "container 1" is created, instead of passing an instance of composite 
> A, it should directly be passed an instance of the root container. That 
> way, "container 1" does not have to go up the tree to find the root 
> container. This makes the proposed "ParentAwareContainerInterface" useless, 
> because finding the root container can be and should be done *before* the 
> container is created.
>
> @XedingUnknown, I understand your concerns that the "delegate lookup 
> feature" of PSR-11 is not backed by a solid interface. After careful 
> consideration, I'm not sure your proposal of adding a getter really solves 
> any issues (because we already can nest several containers). However, you 
> are making clear that we never spoke about the way containers should be 
> created (and who should come first between the parent and the child 
> container). After thinking about your proposal, what is now clear to me is 
> that the parent should be created before the children (and maybe we should 
> stress that out in the META document).
>
> If I was to add another interface, it would more likely be a "container 
> factory" (a la zend-expressive) that can create a container while passing 
> the parent container in parameter:
>
> interface ContainerFactoryInterface {
>     // A composite container could use an array of 
> ContainerFactoryInterface to build containers, passing them the very root 
> container.
>     public function createContainer(ContainerInterface $rootContainer);
> }
>
> @mnapoli, @mweierophinney, any thoughts about this? Do you think we need 
> to consider this or am I overtinking things?
>
> I think we also need to discuss more here the "delegate lookup feature". 
> It is an optional feature, not backed by an interface and this is 
> unprecedented in other PSRs (correct me if I'm wrong but I don't think 
> other PSRs have similar optional features). To the rest of the members 
> here, do you think we should do something special regarding this? 
> Espceially, how should an implementing container advertise that it is 
> supporting PSR-11 with/without delegate lookup feature?
>
> Best regards,
> David.
>
>
> Le vendredi 7 octobre 2016 18:58:51 UTC+2, Xedin Unknown a écrit :
>>
>> Hi all,
>>
>> The delegate lookup feature of Container Interop didn't get as much 
>> attention as I feel it deserves. Specifically, it is lacking formalization 
>> in PHP - an interface. I started this conversation , but was instructed 
>> that the mailing list is the better way to go.
>> It seems that many would agree with me in that it would be great to have 
>> the standard backed by an interface. There was talk of an interface 
>> <https://github.com/container-interop/container-interop/pull/8>, but the 
>> idea was shot down due to forcing the implementation to declare a setter. I 
>> completely agree that forcing a setter is a bad idea.
>> *But why not a getter?*
>>
>> * <https://github.com/XedinUnknown/di>*
>> *XedinUnknown/di <https://github.com/XedinUnknown/di>* is an example of 
>> an implementation that would achieve lookup delegation while depending on 
>> one method of one interface. The rest is implementation details.
>> In short, the container that wishes to delegate must pass its parent (or, 
>> in my implementation, the "root" parent), if set, to the service definition 
>> callable. If the callable is a composite container, it will forward the 
>> call to the first child container that contains the definition. Please find 
>> a more expanded description in the repo's Readme.
>>
>> Looking forward to your comments, questions, or suggestions.
>>
>

-- 
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 php-fig+unsubscr...@googlegroups.com.
To post to this group, send email to php-fig@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/3b0fdce0-507a-40d3-8b68-606f405ee6b8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to