-
Notifications
You must be signed in to change notification settings - Fork 53
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
Replace container-interop/container-interop
v1.2.0
#38
Conversation
With v1.2.0 `container-interop/container-interop` which was released in 02/2017, the package was abandoned. It fully complies with `psr/container`. Replacing it while keeping BC by adding `class_alias` will help upstream projects to finally get rid of `container-interop/container-interop` dependencies. Signed-off-by: Maximilian Bösing <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely 👍 on this.
We need a way to transition easily from WG interfaces to the final published PSR interfaces. I've increasingly noticed the issues that occur when no such path exists, particularly when the final versions from the WG match those in the PSR. (I observed it with PSR-17, PSR-17, and, obviously, PSR-11.). While the PSR packages technically should not care about what happened in WG packages, from an ecosystem perspective, this sort of shim can help aid adoption and prevent the need for BC-breaking new major releases in implementing packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested this, nor investigated that much whether it will have unwanted side effects (I'm trying to be careful here because of the impact of that package).
I'm only adding a +1 for the principle, which is great.
My main concern here is that this implies an added file and aliases for every user of PSR-11, basically forever. On a technical level the aliasing solution is sound, but shouldn't it be in a bridge package (possibly even a later release of container-interop) rather than being in the PSR-11 package permanently? |
@Crell
I did some investigations in the PR mentioned in #37 (PR). I've added integration tests which verify that the
(I guess that, if the latter works, property type-hints will work as well?) So regarding unwanted side-effects, I guess I got these covered (as this package only provides 3 interfaces). |
I’m a little bit concerned about having an additional file to be included and required basically at every request even if not used. In the specific case every user of this package will pay for this change even if they haven’t had any reference to the old container interop interfaces. While the solution is technically good (even if For these reasons this is a 👎 for me. |
Hm, limiting it to the 1.x package helps some, but as of right now that's 99% or more of all users of this package. (cf: https://packagist.org/packages/psr/container/stats). So, it's still basically everyone. I would rather this bridge file exist either in its own package, or in a final release of the container-interop package. |
Copying my thoughts from discord:
|
I encourage everyone participating to use numbers and concrete use cases/arguments. It's hard to move forward based on feelings and/or abstracts "what if".
Why? If this is a performance penalty, can you quantify it? With opcache and possible Composer optimizations, it may not be as obvious as it sounds.
Why?
But then that defeats the purpose of removing dependencies to container-interop. What would be the advantages of what you suggest over the current situation?
Why?
Could you illustrate the kind of problems to expect? Do you mean other PSRs could do the same? If that's the case, wouldn't we simply reject any problematic pull request during code review (in other words, why would we assume that merging a pull request automatically means we'd accept similar pull requests). We have no obligations to merge bad things just because something remotely similar was once merged in another package in the past.
v2, as suggested above? |
I'm on holiday now, I cannot quantify anything until I return to work. Anyway this is not a "what if": an
Because I think that ->
I can explain this better: in my opinion, importing foreign symbols into a package in order to deprecate another package is not correct in general: is responsibility of the package which is being abandoned/deprecated to provide an upgrade path to a maintained package.
This PR does not contain any deprecation notice. Using this, the user will not see any notice (not at run time nor while installing the package through composer). This said, a possible solution is to split those three For example the <?php
namespace Interop\Container;
use Psr\Container\ContainerInterface as PsrContainerInterface;
trigger_error('The interface Interop\\Container\\ContainerInterface is deprecated. Please use Psr\\Container\\ContainerInterface instead.', E_USER_DEPRECATED);
class_alias(PsrContainerInterface::class, ContainerInterface::class); This will register the alias only on usage and also trigger a deprecation notice on first inclusion. |
IMHO - Runtime deprecations should be avoided. But if thats how this can make it into this package, I'll take it.
I guess thats a consensus. However, the container-interop was in fact the blue print for this package, thats why it was that easy to simply extends the PSR Interfaces in its latest version. I don't think that such combination of pre-created drafts will land in real userland Code again as it was done for the container interop by zendframework, pimple and many others. But dependency injection is the key principle of modern projects and thus its widely used. |
@alekitto and @KorvinSzanto I don't fully understand your concerns, but let me try and outline what I see as the situation at hand. container-interop existed as the codebase for the PSR-11 WG. One of the requirements for an acceptance vote is that there are multiple concrete implementations of the standard. As such, we had many different projects that adopted container-interop in order to validate the standard. For these implementations to be tested, they needed releases, and many of them chose to release new versions that then pinned to container-interop. When PSR-11 was released, several things happened. First, container-interop was updated to (a) include a dependency on the PSR-11 interfaces, (b) have its own interfaces extend the PSR-11 interfaces, and (c) mark itself deprecated. The idea behind this was for it to bridge between the WG and the ratified PSR; generally speaking, you could use PSR-11 in place of container-interop, but you'd get a warning during installation that it is out-of-date. This was essentially the bridge package that Korvin suggested! However, there are issues with this approach. Code that has a return type of the container-interop As such, if a DI implementation has defined its own interfaces or has implementations that have container-interop type hints for method arguments, they MUST release a new major version in order to guarantee backwards compatibility. Considering DI is often a foundational layer of a framework, this has huge knock on effects. As an example, for Laminas, we'd have 34 different packages that would then require new major versions in order to update to the a new laminas-servicemanager version that is functionally the same, because they create implementations of interfaces defined in laminas-servicemanager that typehint against container-interop. And that's just our packages; who knows how many third party libraries or userland applications are creating these implementations and would require updates. In the early days of FIG, we generally developed in the same namespace as the final specification. When we adopted the v3 by-laws and moved to working groups (which has been TREMDENDOUS), we made a recommendation that WGs use a different namespace. The scenario I outline above was a side effect of that that we didn't anticipate. We badly need a process to make it easier for those projects that help in the specification process to adopt the final standard. What is proposed here is one possible solution to that. Yes, these projects need to update to the official namespaces; I'm not arguing that at all. But I think we also need to recognize that these projects have end users, and that requiring libraries to bump major versions to bump to functionally equivalent code is a huge headache for those end users. I've seen the following arguments against the proposed solution in this thread:
My larger point is we need a process for migrating from WG to PSR interfaces for those libraries that participated in testing the specification that does not automatically require BC-breaking new major versions. This is one such solution, based on observing the shortcomings of a previous solution. Unless there are demonstrable technical problems with the proposal, I'm not seeing a down side, and see only benefits for the larger ecosystem of users. |
@weierophinney The issue is clear and the solution is technically correct. As I previously said, I'd prefer not to merge this solution in this package but in a later release of
I understand your point of view, but I disagree: IMO those are foreign symbols as they are declared in another package. If we consider this as an exception to this rule we can set a bad example and make the things easier when we would consider another exception. Please don't do this, not in a package that is defining a standard.
If someone has time could measure it (unfortunately my computer is at hundreds of kilometres away from me). But still, I know for sure that none of my projects includes
This could be solved in various ways: for example another version of the Polluting this package with symbols inherited from the WG package should be the last resource. As a last resource, declaring the deprecated namespace to this package and splitting the three |
This is a non-starter - it just perpetuates the issues we have currently.
This was our original plan. But it doesn't resolve the issue for the larger PSR-11 ecosystem, and, instead, requires each container-interop implementation to perform such mitigation, which can in turn lead to other issues down the line. As an example, if a user was composing two different PSR-11 implementations in their application, and each implementation defined such aliases, we now have a scenario where there a conflict, depending on the approach:
It can be done if each package also does a test for Summary of the above:
The main problem with this approach, while workable, is that if another package is loaded ahead of your own, it could define the aliases differently, which could lead to breakage. I don't anticipate that happening when aliasing against FIG interfaces, but it cannot be ruled out. For me, this is yet another reason to create a process for such scenarios in future specifications, whether that's replicating the WG artifacts in the official package, creating a final release of the WG package that does this, or something else. Whatever the solution is, it needs to be something that makes the transition transparent for packages implementing the WG interfaces, and allows them to do minor, versus major, releases to update to the final specification. |
Absolutely agree! This discussion is a result of lack of such a specification. If we write down how the things should be handled transitioning from WG package to PSR package, we resolve discussions like this on package publish. But probably we should discuss it on another channel. About the situation you described in the previous comment: is this a "what if" or do you have a real use case? In case what do you think about the third solution? |
Real use case. In the mezzio-skeleton package, for instance, we have dev requirements on multiple container packages so we can test and ensure that each works with the skeleton as expected. Additionally, I've used containers that can proxy to other PSR-11 instances (e.g., auto-wiring DI containers that will proxy to non-wiring instances as an optimization). Which third solution are you referring to?
Your proposal is essentially this one, with a minor strategic difference (only alias something that is consumed), and addresses all the concerns I had (which are preventing conflicts between implementing packages, while simultaneously giving them an automatic upgrade to PSR-11). I prefer it over my own solution, because in my own, I see a potential for issues if implementing packages that adopt the approach do not all alias to the PSR-11 interfaces. |
@weierophinney I was referring to the first one (aliases split on multiple files). If there's consensus on it, it could be an acceptable solution stating than this package is a direct continuation of the deprecated package. |
@boesing Okay, so I think we have a solution:
On the maintainers end, we'll need to create a 1.2.x branch, and then we would merge this to that branch for a 1.2.0 release, but NOT merge it to the master (2.0.x) tree (which does not define those aliases) From there, implementations can then choose how/when to update type hints and implementations, but finally have the option to do so in a new minor instead of a new major. |
This... isn't true? There is no such recommendation anywhere in the bylaws. PSR-11 was passed under the v2 era rues. (That's why the meta document lists an Editor, Sponsor, and Contributors, not the Working Group. There technically wasn't one, even though in practice that's how it was managed.) Nothing in FIG v3 says to use a separate namespace, and for PSR-14, for instance, we didn't do so, and worked directly in the So this is a problem that applies only to 1) Specs that chose to use a separate namespace during development and 2) projects that released real versions of their libraries that depended on that development repository (which is not required by FIGv3 procedures; it says "trial implementation" very specifically to avoid that). That is, in fact, a very unusual situation. If it's not unique to PSR-11, it's at least an unusual one. That's why I am not supportive of making the fix something within the psr/container package itself. Using class aliases as a way for projects to more easily jump from the -interop package to the psr/container package makes sense. I don't think anyone is disagreeing on that. Just on where that aliasing lives. I agree that there should also be one(1) such alias package in existence, not one per project. I... have no idea where the "3 separate files is better than one" bit came from, though. What I don't understand is why it must be in this package. What would not-work about releasing a container-interop 1.3 or 2.0 that contained nothing but this same bridge file? Consumers of container-interop could update to that, and get a situation where those two names are aliased to each other. Then they can switch their type definitions without incident. Then at some point in the future change to use the |
I've experienced it with PSR-11, PSR-15, PSR-17, and PSR-18. It's not unusual at all at this point.
The primary reason is that the container-interop package is already marked deprecated. Its because it is marked deprecated that we see people asking if implementors can remove dependencies on it. If the WG were to release a new version, then the question is if that version would also be marked deprecated? The scenario wouldn't be as bad as it is today, because it could be used in a transition release, with the following workflow:
This would likely work fine, as the deprecation messages would go away very quickly for a majority of users who keep their applications on up-to-date dependencies. We could even suggest users at least specify a dependency on container-interop 1.3.0 in their applications and update their own code to reference solely PSR-11 as a way to become forwards compatible. I'd still like to see this documented somewhere in FIG for editors and working groups so they can plan for what happens when transitioning the WG to accepted specification, so we don't have future issues like this. @mnapoli, would this work for you? If so, I can prepare the patch for container-interop. (I don't have commit rights there, I don't think...) |
Per discussion on php-fig/container#38, this patch updates the three shipped interfaces to instead become class aliases for the official PSR-11 interfaces. This allows implementing libraries to immediately switch to PSR-11 typehints/implementations while retaining backwards compatibility with container-interop. The patch also includes documentation of workflows for moving from container-interop to PSR-11 for both package and application authors.
As realized in container-interop/container-interop#97, a new major version is required to avoid BC breaks where upstream libraries/projects do implement both Thanks for your feedback in here, this led us to a better solution by adding changes to |
NOTE
Since there is no 1.2.x branch, this PR targets 1.1.x.
Description
With v1.2.0
container-interop/container-interop
which was released in 02/2017, the package was abandoned. It fully complies withpsr/container
.Replacing it while keeping BC by adding
class_alias
will help upstream projects to finally get rid ofcontainer-interop/container-interop
dependencies.Closes #37