Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[DI] Inline trivial private servives #23674

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

Merged
merged 1 commit into from
Jul 28, 2017
Merged

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekas nicolas-grekas commented Jul 26, 2017

Q A
Branch? 4.0
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets -
License MIT
Doc PR -

There is no need to generate a method when the instantiation is just as verbose as calling that method.

*
* @return bool
*/
private function isTrivialInstance(Definition $definition)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this method name (isTrivialInstance()) which feels like an internal detail, maybe we could use a more generic and future-proof name, such as canBeInlined() ?

Copy link
Member Author

@nicolas-grekas nicolas-grekas Jul 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, as a private method, this is an internal detail :)
more importantly, the "trivial" is important here. It's not only that the instantiation can be inlined, it's also that the instantiation is trivial, this meaning that it mostly a simple new Foo().
More complex instantiation would also be inlineable (eg Factory::create(new Foo($this->get('bar')))), but we don't want to inline those (we need a limit, being trivial is the one, for what it means (it only means whatever logic is in the method, see patch :) .)
In this respect, canBeInlined() would be confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. My reasoning was that in the future, if you add new optimizations, the code will complicate a lot (if ($this->isTrivialInstance() || $this->isServiceLengthSmall() || $this->isDevEnvironment()) vs if ($this->canBeInlined()) and then adding more optimizations to that method).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, if in the future we decide that more cases would benefit from this, we could still change the defining of what a trivial service is. And we can decide to rename the method if actually necessary.

canBeInlined has another reason to be confusing: we have another concept called inlining in the component (although a bit related)

Copy link
Member

@stof stof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it actually be done in 3.4 ? Private services can still be accessed there, even though it is deprecated. I think your code breaks it.

}

foreach ($definition->getArguments() as $arg) {
if (!$arg || ($arg instanceof Reference && 'service_container' !== (string) $arg)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the special case about referencing the container ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because this considers new Foo($this) a trivial case ($this being the dumped container reference of course)

@nicolas-grekas nicolas-grekas changed the base branch from 3.4 to master July 26, 2017 08:34
@nicolas-grekas nicolas-grekas modified the milestones: 4.0, 3.4 Jul 26, 2017
@nicolas-grekas
Copy link
Member Author

Can it actually be done in 3.4 ? Private services can still be accessed there,

Hum right, rebased now

if (!$v || ($v instanceof Reference && 'service_container' !== (string) $v)) {
continue;
}
if (!\is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be careful. null is not a scalar, but it is a trivial value

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null will be handled by if (!$v just above

@nicolas-grekas nicolas-grekas force-pushed the di-trivial branch 3 times, most recently from 1017368 to f96fc19 Compare July 26, 2017 09:59
@@ -125,6 +125,7 @@
$container
->register('factory_simple', 'SimpleFactoryClass')
->addArgument('foo')
->setDeprecated(true)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this to have at least one private service that cannot be inlined.

@nicolas-grekas
Copy link
Member Author

fabbot failure is false positive, PR ready.

@@ -38,7 +38,7 @@ public function isProxyCandidate(Definition $definition);
*
* @return string
*/
public function getProxyFactoryCode(Definition $definition, $id, $methodName);
public function getProxyFactoryCode(Definition $definition, $id, $methodName = null);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spotted meanwhile: not allowing null breaks our forward compat policy (being able to upgrade a 3.4 code so that it works with 4.0)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure about that ? Implementors are allowed to add = null for their argument even if the interface does not have it (the opposite is false).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I mean, we can make the argument required in 4.0. It will not forbid making 3.4 code compatible with 4.x (you need to make the argument optional in your implementation to support the 3.4 interface, but this does not forbid 4.x to make it required in the interface)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, dunno why I did that now :) reverted

@fabpot
Copy link
Member

fabpot commented Jul 28, 2017

Thank you @nicolas-grekas.

@fabpot fabpot merged commit 0caed93 into symfony:master Jul 28, 2017
fabpot added a commit that referenced this pull request Jul 28, 2017
This PR was merged into the 4.0-dev branch.

Discussion
----------

[DI] Inline trivial private servives

| Q             | A
| ------------- | ---
| Branch?       | 4.0
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

There is no need to generate a method when the instantiation is just as verbose as calling that method.

Commits
-------

0caed93 [DI] Inline trivial private servives
@nicolas-grekas nicolas-grekas deleted the di-trivial branch July 28, 2017 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants