Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
Not allowing autoconfigure, instanceofConditionals or defaults for ChildDefinition#22563
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Not allowing autoconfigure, instanceofConditionals or defaults for ChildDefinition#22563
Uh oh!
There was an error while loading.Please reload this page.
Conversation
335b11b to9939921Compare4944a47 to710d9a8Compareweaverryan commentedApr 28, 2017
This should be finished now. It highlights a clear philosophy: basically, when you set a Yourparent classcan still take advantage of these... and most of those settings will cascade onto the child (notably, not tags, consistent with child/parent functionality). So, your parent's Definition is configured... andthen that's applied to the child. Also in this PR (but a bit related): weprevent Again, please check the test cases in the Cheers! |
nicolas-grekas left a comment• edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
👍
100% agree with Ryan's comments, this is required to make things consistent and remove the need for multidimensional merges that have no generic solutions.
simensen commentedApr 28, 2017
In talking about this with@weaverryan today, I asked under what circumstances might people want to use Personally, I've only used Said another way, it feels like |
…ildDefinitionAlso, not allowing arguments or method calls for autoconfigure. This is a safetymechanism, since we don't have merging logic. It will allow us to add this in thefuture if we want to.The reason is that parent-child definitions are a different mechanism for "inheritance"than instanceofConditionas and defaults... creating some edge cases when trying tofigure out which settings "win". For example:Suppose a child and parent definitions are defined in different YAML files. Thechild receives public: false from its _defaults, and the parent receives public: truefrom its _defaults. Should the final child definition be public: true (so the parentoverrides the child, even though it only came from _defaults) or public: false (wherethe child wins... even though it was only set from its _defaults). Or, if the parentis explicitly set to public: true, should that override the public: false of thechild (which it got from its _defaults)? On one hand, the parent is being explicitlyset. On the other hand, the child is explicitly in a file settings _defaults publicto false. There's no correct answer.There are also problems with instanceof. The importance goes: defaults < instanceof < service definitionBut how does parent-child relationships fit into that? If a child has public: falsefrom an _instanceof, but the parent explicitly sets public: true, which wins? Shouldwe assume the parent definition wins because it's explicitly set? Or would the_instanceof win, because that's being explicitly applied to the child definition'sclass by an _instanceof that lives in the same file as that class (whereas the parentdefinition may live in a different file).Because of this,@nicolas-grekas and I (we also talked a bit to Fabien) decided thatthe complexity was growing too much. The solution is to not allow any of thesenew feature to be used by ChildDefinition objects. In other words, when you want somesort of "inheritance" for your service, you should *either* giving your service aparent *or* using defaults and instanceof. And instead of silently not applyingdefaults and instanceof to child definitions, I think it's better to scream that it'snot supported.
710d9a8 toa943b96Comparetheofidry commentedApr 28, 2017
👍 for that PR. You could still need a parent to extend a definition of a library, so I don't think parent should be deprecated. |
fabpot commentedApr 28, 2017
@simensen we had this discussion during DrupalCon with@weaverryan and@nicolas-grekas and we came to the same conclusion. We should deprecate |
fabpot commentedApr 29, 2017
Thank you@weaverryan. |
…defaults for ChildDefinition (weaverryan)This PR was merged into the 3.3-dev branch.Discussion----------Not allowing autoconfigure, instanceofConditionals or defaults for ChildDefinition| Q | A| ------------- | ---| Branch? | master| Bug fix? | yes (removing risky behavior)| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | see#22530| License | MIT| Doc PR | n/aThis PR *prohibits* using `autoconfigure`, `_instanceof` and `_defaults` for ChildDefinition.Additionally, I added many "integration" test cases: we need to test and prove all edge cases. These are in the `integration/` directory: the `main.yml` file is parsed and compared to `expected.yml`. Both are in YAML to ease comparing the before/after. We need to check these out and make sure they're right and we're not missing anything else.This PR removes MANY of the "wtf" cases, but there are still 4 that I know of... and of course they all deal with parent-child stuff :).A) [MAJOR] [autoconfigure_parent_child_tags](https://github.com/symfony/symfony/pull/22563/files#diff-fd6cf15470c5abd40156e4e7dc4e7f6d) `instanceof` tags from autoconfigure are NEVER applied to the child (you can't set `autoconfigure` directly on a Child, but you still can set it on a parent and inherit it... sneaky). We could throw an Exception I suppose to prevent this `autoconfigure` from cascading from parent to child... but it's tricky due to `instanceof`.B( [MAJOR] [instanceof_parent_child](https://github.com/symfony/symfony/pull/22563/files#diff-14666e9a25322d44b3c2c583b6814dc2) `instanceof` tags that are applied to the parent, are not applied to the child. Again, you can't set `instanceof` directly on a Child, but you *can* set it on a parent, and have that cascade to the child. Like before, we could maybe throw an exception to prevent this.C) [MINOR] ([autoconfigure_child_not_applied](https://github.com/symfony/symfony/pull/22563/files#diff-3372a1dcaf3af30d14a7d0a6c8bfa988)) automatic `instanceof` will not be applied to the child when the parent class has a different (non-instanceof-ed) class. If we could throw an exception for (A), then it would cover this too.D) `_tags` from defaults are never used (unless you have inherit_tags) - fixed in#22530A, B & C are effectively caused by there being a "sneaky" way to re-enable `autoconfigure` and `instanceof` for ChildDefinition... which opens up wtf cases.## Wait, why not support `_defaults`, `autoconfigure` and `_instanceof` for child definitions?1 big reason: reduction of wtf moments where we arbitrarily decide override logic. PLUS, since `_defaults`, `instanceof` and `autoconfigure` *are* applied to parent definitions, in practice (other than tags), this makes no difference: the configuration will still pass from parent down to child.Also, using parent-child definitions is already an edge case, and this *simply* prevents *just* those services from using the new features.## Longer reasons whyThe reason behind this is that parent-child definitions are a different mechanism for "inheritance"than `_instanceof` and `_defaults`... creating some edge cases when trying to figure out which settings "win". For example:```yml# file1.ymlservices: _defaults: public: false ChildService: parent: parent_service# file2.ymlservices: _defaults: public: true ParentService: ~```Is `ChildDefinition` `public: true` (so the parentoverrides the child, even though it only came from _defaults) or `public: false` (wherethe child wins... even though it was only set from its _defaults)?Or, if ParentService is explicitly set to `public: true`, should that override the `public: false` of ChildService (which it got from its `_defaults`)? On one hand, ParentService is being explicitlyset. On the other hand, ChildService is explicitly in a file settings `_defaults` `public: false`There's no correct answer.There are also problems with `_instanceof`. The importance goes:> defaults < instanceof < service definitionBut how do parent-child relationships fit into that? If a child has public: falsefrom an _instanceof, but the parent explicitly sets public: true, which wins? Shouldwe assume the parent definition wins because it's explicitly set? Or would the_instanceof win, because that's being explicitly applied to the child definition'sclass by an _instanceof that lives in the same file as that class (whereas the parentdefinition may live in a different file).Because of this,@nicolas-grekas and I (we also talked a bit to Fabien) decided thatthe complexity was growing too much. The solution is to not allow any of thesenew feature to be used by ChildDefinition objects. In other words, when you want somesort of "inheritance" for your service, you should *either* giving your service aparent *or* using defaults and instanceof. And instead of silently not applyingdefaults and instanceof to child definitions, I think it's better to scream that it'snot supported.Commits-------a943b96 Not allowing autoconfigure, instanceofConditionals or defaults for ChildDefinition
Uh oh!
There was an error while loading.Please reload this page.
This PRprohibits using
autoconfigure,_instanceofand_defaultsfor ChildDefinition.Additionally, I added many "integration" test cases: we need to test and prove all edge cases. These are in the
integration/directory: themain.ymlfile is parsed and compared toexpected.yml. Both are in YAML to ease comparing the before/after. We need to check these out and make sure they're right and we're not missing anything else.This PR removes MANY of the "wtf" cases, but there are still 4 that I know of... and of course they all deal with parent-child stuff :).
A) [MAJOR]autoconfigure_parent_child_tags
instanceoftags from autoconfigure are NEVER applied to the child (you can't setautoconfiguredirectly on a Child, but you still can set it on a parent and inherit it... sneaky). We could throw an Exception I suppose to prevent thisautoconfigurefrom cascading from parent to child... but it's tricky due toinstanceof.B( [MAJOR]instanceof_parent_child
instanceoftags that are applied to the parent, are not applied to the child. Again, you can't setinstanceofdirectly on a Child, but youcan set it on a parent, and have that cascade to the child. Like before, we could maybe throw an exception to prevent this.C) [MINOR] (autoconfigure_child_not_applied) automatic
instanceofwill not be applied to the child when the parent class has a different (non-instanceof-ed) class. If we could throw an exception for (A), then it would cover this too.D)
_tagsfrom defaults are never used (unless you have inherit_tags) - fixed in#22530A, B & C are effectively caused by there being a "sneaky" way to re-enable
autoconfigureandinstanceoffor ChildDefinition... which opens up wtf cases.Wait, why not support
_defaults,autoconfigureand_instanceoffor child definitions?1 big reason: reduction of wtf moments where we arbitrarily decide override logic. PLUS, since
_defaults,instanceofandautoconfigureare applied to parent definitions, in practice (other than tags), this makes no difference: the configuration will still pass from parent down to child.Also, using parent-child definitions is already an edge case, and thissimply preventsjust those services from using the new features.
Longer reasons why
The reason behind this is that parent-child definitions are a different mechanism for "inheritance"
than
_instanceofand_defaults... creating some edge cases when trying to figure out which settings "win". For example:Is
ChildDefinitionpublic: true(so the parentoverrides the child, even though it only came from _defaults) or
public: false(wherethe child wins... even though it was only set from its _defaults)?
Or, if ParentService is explicitly set to
public: true, should that override thepublic: falseof ChildService (which it got from its_defaults)? On one hand, ParentService is being explicitlyset. On the other hand, ChildService is explicitly in a file settings
_defaultspublic: falseThere's no correct answer.
There are also problems with
_instanceof. The importance goes:But how do parent-child relationships fit into that? If a child has public: false
from an _instanceof, but the parent explicitly sets public: true, which wins? Should
we assume the parent definition wins because it's explicitly set? Or would the
_instanceof win, because that's being explicitly applied to the child definition's
class by an _instanceof that lives in the same file as that class (whereas the parent
definition may live in a different file).
Because of this,@nicolas-grekas and I (we also talked a bit to Fabien) decided that
the complexity was growing too much. The solution is to not allow any of these
new feature to be used by ChildDefinition objects. In other words, when you want some
sort of "inheritance" for your service, you shouldeither giving your service a
parentor using defaults and instanceof. And instead of silently not applying
defaults and instanceof to child definitions, I think it's better to scream that it's
not supported.