-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Make as many services private as possible #23822
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
Comments
Can we make a list of those services so the community can submit PRs making them private ... or do you prefer to work on this yourself? Thanks. |
I think we can make a list, it will a lot of work for only one person :) |
In the Symfony Demo upgraded to Symfony 3.3.6 and Symfony Flex I see a lot of services that could be removed. For example, most of these services related to translation:
|
there is an issue about doing this in 3.4: if they get referenced only once or not at all, they will be inlined and removed, which forbids accessing them through Btw, we don't have any upgrade path for switching a service to private (be it a core service of an internal services). I suggest adding a feature for that. |
@javiereguiluz The |
@stof there is another option, which is much lighter: we create two special public services, deprecated ones, that references them all. |
@nicolas-grekas note that the feature I'm talking about to deprecate public access to services should not go away in 4.0, as 4.x+ of Symfony may still want to do such changes in the future (and then, we don't even have the private get BC layer for private services referenced multiple times), and external bundles will have the same need too (once they start dropping support for Symfony < 3.4, most of their services won't need to be public either) Your proposal about using a special deprecated public services is not fine:
|
Of course, I was seeking for the laziest plan :) |
To really make translations loading lazy we'd need something like this #17563 right? |
👍 for introducing what @stof suggests, it would be useful for many third party bundles for sure. |
Here is the plan:
That would allow bundles to still have the services public with <3.3, trigger the deprecation with 3.4, and have the services really private when used with 4.0. (I'm still trying to not have to create and maintain a feature to move from public to private on the long term) |
Some comments posted on #23867 (which is now closed): From @Tobion:
Then from @fabpot:
Then me:
|
The difference for private services is not only the inlining, but also the removal indeed (as the container is able to ensure that they won't ever be needed, as they are forbidden for dynamic retrieval). |
@stof if there was no performance difference between removing or not removing private services, then the distinction is not neccessary. |
…e services (nicolas-grekas) This PR was merged into the 3.4 branch. Discussion ---------- [FrameworkBundle] Fix Di config to allow for more private services | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This PR is a prelude to #23822: - allow cache pool clearers to be private by using IGNORE_ON_UNINITIALIZED_REFERENCE, allowing much more sane logic in the related passes - allow templating helpers to be private by using a service locator - replace an inline def by a reference in workflow's config (ping @lyrixx @Nyholm) - fix the Stopwatch alias, which is public in 3.4, but private in 3.3 - remove direct access to `->get('fragment.handler')` in tests so that the service could be made private Commits ------- 76c4217 [FrameworkBundle] Fix Di config to allow for more private services
…kas) This PR was merged into the 3.4 branch. Discussion ---------- Make as many services private as possible | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | not yet | Fixed tickets | #23822 | License | MIT | Doc PR | - - [x] review the list of currently public services and validate which one should be turned private (noted as such with the `container.private` tag in this PR) - [x] rebase on top of #24103 - [x] implement the behavior described in #23822 (comment) - [x] add tests List of services that will be kept public: ### Remaining public aliases cache.app_clearer <- for the cache:pool:clear command to clear app pools $commandId <- for non-lazy commands which are get() at runtime router <- for the base controller templating <- for the base controller ### Remaining public services test.client <- for WebTestCase security.password_encoder <- for use in ContainerAware classes security.authentication_utils <- for use in ContainerAware classes filesystem <- for use in ContainerAware classes kernel <- for use in ContainerAware classes translator <- for use in ContainerAware classes validator <- for use in ContainerAware classes cache_clearer <- for the cache:clear command cache_warmer <- required to bootstrap the kernel cache.app <- for userland only cache.global_clearer <- for the cache:pool:clear command to clear all pools cache.system <- for userland only data_collector.dump <- required to have dump() work very early when booting the kernel event_dispatcher <- required to wire console apps form.factory <- for the base controller http_kernel <- required to bootstrap the kernel profiler <- used in tests request_stack <- for the base controller routing.loader <- used by routing security.authorization_checker <- for the base controller security.csrf.token_manager <- for the base controller security.token_storage <- for the base controller serializer <- for the base controller session <- for the base controller state_machine.abstract <- userland state machines workflow.abstract <- userland workflows twig <- for the base controller twig.controller.exception <- controllers referenced by routing twig.controller.preview_error <- controllers referenced by routing var_dumper.cloner <- required to have dump() work very early when booting the kernel web_profiler.controller.exception <- controllers referenced by routing web_profiler.controller.profiler <- controllers referenced by routing web_profiler.controller.router <- controllers referenced by routing Commits ------- 1936491 Make as many services private as possible
My thoughts after trying
This means almost all the Symfony libraries will have to be updated for Symfony 4... Did we measure what is the performance improvement on such change that would justify this? :) |
It's not only about perf, it's also a lot about design. Bundles don't care about this public/private difference, so that everything is usually public, thus open to service location. |
@sroze the fact that the default visibility of services is changing indeed means that bundles have to be updated. But they can be updated in 2 different ways (depending on the services):
|
@sroze I gave the same feedback to @nicolas-grekas a few days ago. Upgrading to Symfony 4 is almost impossible. I was luck enough to have write access to almost all bundles that had problems, but I'm in a very special position in this regard. Moreover, the error message is very difficult to understand and I think people won't understand how to fix the issue. @nicolas-grekas @sroze You're missing the point. First, it's not true that bundles are making services private. We never said that bundles should done that. |
Regarding the error message being difficult to understand, this is something we could work on during the stabilisation phase. |
I agree with the idea that it would be nice to have libraries providing clear extension points (I guess that's what you are trying to solve with private services by default). Still, if the main reasons are nice-to-have design-thinking and not-proven performances improvements, I guess that's still a debatable choice to force all the existing ecosystem to update. I'd go as far as saying that now that we have timely-based releases, it's not because we can break the BC at each major version that we should 😛 I'd follow on @fabpot's argument: private services were never a communicated best practice. I'd much more prefer a documentation approach (and also "blaming" libraries exposing too much) than enforcing it at the framework level, or we are going to have unhappy users all the way from 3.x to 4.x. |
Don't take me wrong, design is not a nice-to-have: it's something ppl expect their framework to help them do better.
I'm telling this all the day while reviewing PRs so I know that for sure. Here making services public in an explicit way is VERY easy, so the required fix is trivial. That's not an excuse, but a balanced argument: if it's easy to do while improving the architecture of all SF apps, that's worth it. |
Alright, I went a bit to far with "nice-to-have". It's definitely not right to say that "nobody cares" about the design so let's not drop the private/public distinction. There is still three points:
The point 1) makes me think that: maybe introducing another property, called What about the following:
|
There are many services which are public right now but have not reason to be.
The text was updated successfully, but these errors were encountered: