following the PSR-7 process I started to think that the FIG group has already matured but when I read this PSR and realized that it is real joke I was shocked. It's not that it would be messy or badly prepared, the job is done well, but the problem is that it shows how badly people tend to understand the concept of DI. Even worse - it shows that even the people from FIG doesn't seem to understand the DI which is really alarming - it basically show the PHP community is in the hands of immature self-proclaimed "PHP FIG" group.
Now, don't get me wrong, even if some of the standards had some controversy in them, it's great to actually have the standards (PSR-0, PSR-1, PSR-2, PSR-4, PSR-7) and I really appreciate the work and the fact the you guys did it. And even if I would do some things differently the main point is the fact we have the standards. PSR-7 for instance will open a new era of framework interoperability.
Having said that and looking at the other PSRs, there is absolutely no place among these standards for what you call "PSR-Container". There are very serious issues with this PSR and I'll try to explain why:
First and the most obvious reason - the meta document says "By standardizing the way entries are fetched from a container, frameworks and libraries using the Container PSR could work with any compatible container." Now, if we are talking about DI, I say just "what?" What entries fetching? Why on earth should this be standardized? There's apparently a huge misunderstanding among the people who prepared this what DI actually is. The point of DI container is not that you use it to fetch services everywhere and thus you need an interface to that (that would be a simple global service locator) - the main point of a correctly used DI container is that your application actually doesn't even know that it exists!
Now, this is extremely important - a well-designed application knows nothing about the DI container, in fact you only need to configure it and fetch one service in your bootstrap script. For instance $container->getByType(Symfony\Component\Console\Application::class)->run() or $container->getByType(Nette\Application\Application::class)->run(), etc. Now, do we really need a standard for fetching one service? Of course not, but there's more...
I used the getByType method on purpose since the best DI containers I know use autowiring (many "DI" containers aren't even a real DI). The authors of this PSR probably think they didn't forget about autowiring since they mention "the identifier is the class name, or an interface name (used mostly by frameworks with an autowiring capability)" - well, that's wrong. Autowiring is a great feature of DI containers but it doesn't replace service names. Why? Because not everything should be autowired. Typically, if you have more instances of the same interface (and that's really not uncommon) you may autowire only one of them and reference the rest by names. Sure, you usually do the references only inside the configuration file, because at the end you can fetch just one service, but that doesn't vindicate the correctness of the interface you've proposed.
And now coming to the big hype called container interoperability - I've seen you use this as a (wrong) excuse any time somebody points out this PSR is wrong or that it has nothing to do with DI. The response (excuse) in the discussions usually was "it's actually not for a container but for container interoperability" - huh? I guess you can't be more wrong. So you are saying you want us to use 5 different containers in your application and connect them by your fantastic interface? Is it really possible that somebody can even mean this seriously? I'll try to explain what's the problem:
The future of all the PHP packages that are getting really great lately is that they will be (or are) usable in basically any framework and the best way (not the only way) to get them to your framework is a good DI. Eventually, the DI will be the only package that will be specific for your "framework" - this basically means that there will be no framework, but rather many small packages - and we already see that happening. Every programmer will chose his DI implementation and a set of packages and configure them with that DI. Simplified, that's the general view. Now, can anybody tell my why would I need the container to have a standard interface and why would I need more containers connected together? Do you realize that a great container with autowiring-resolving capabilities simply cannot interoperate with another one that doesn't have these capabilities? You add a service to your config file that is registered in the second-non-autowiring container and you expect your great container to autowire any services that are in your container and at the same time in your class' constructor and... it simply won't happen. And no ContainerInterface can ever save that.
To sum it up:
- We don't need ContainerInterface for fetching services because the correct way is not knowing about it in the code (except fetching one service in bootstrap).
- You can't mix autowiring and fetching by service names in the same method. Doing so is a misunderstanding of basic autowiring principles.
- Container interoperability is a wrong pattern and it cannot be used among containers with different capabilities (the problem is especially autowiring).
- You seem to think that a simple global service locator is the same as DI Container. The interface you've proposed and the interoperability you are talking about would work in the case of service locator.
Some applications can use DI, some applications service locator, some applications singleton environment, some static environment... and there are tons of other configuration options. Therefore, there MUST NOT be a standard for that because it is simply not possible to standardize such a thing.
Btw. Kris had really good points and questions and non of you was able to answer it. Please, answer to his questions and think about them. Responses like "read the meta document" are just arrogant and show you don't want to think about this PSR yourselves. I totally agree with Kris that standardizing a way of actually configuring a container would be much more useful (althougth probably hard to do).
In the end I would again than the FIG group for all other hard work and ask - please take these serious issues into consideration and don't smash me with a "you didn't read..." - I did and I say it's wrong in many ways.
(PS: Checking Twitter it seems I'm not the only one who have noticed this PSR is a big misunderstanding of DI Container vs. Service Locator.)
Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):