Skip to content
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

Using typed properties on public/protected properties #43600

Closed
nicolas-grekas opened this issue Oct 20, 2021 · 11 comments · Fixed by #45360
Closed

Using typed properties on public/protected properties #43600

nicolas-grekas opened this issue Oct 20, 2021 · 11 comments · Fixed by #45360

Comments

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Oct 20, 2021

Right now, we added types to private/final/internal properties only because they're the only ones we can change without breaking BC.

For public/protected properties, adding a type breaks BC when a child class redeclares an existing properties. The reason is that redeclared properties must have the exact same type and their parent properties. Neither variance nor covariance is allowed for properties.

Since it'd still be nice to add types to them, can we draw a migration path?

The only path I see is to throw a deprecation when a child class redeclares a property.

The only reason I see for redeclaring a public/protected property is to change it's default value.
For non-static public/protected properties, it should always be possible to use the constructor if a different initial value is desired. As such, we could unconditionally throw a deprecation notice in DebugClassLoader when an untyped non-static property is found. Alternatively, we could we make this deprecation opt-in, eg reusing @final on properties, but I don't see the benefit of doing so since I anticipate that all such properties would have the annotation.

For static properties, I'm not sure I see a migration path. But where do we use public/protected static props in core? I can think of command names/descriptions. Those can already be replaces by attributes. So maybe the path forward is to turn them all into attributes? We'd need to investigate the codebase to have a clearer picture on that.

@derrabus
Copy link
Member

derrabus commented Oct 20, 2021

As such, we could unconditionally throw a deprecation notice in DebugClassLoader when an untyped non-static property is found.

This would cause a lot of confusion especially if we do this on classes that don't extend Symfony classes.

But where do we use public/protected static props in core?

public static $statusTexts = [

There's a handfull of places where we have public static properties. Those are grep-able. 🙂

For most cases I've found, I'd say that we expect those properties to be set from outside, but not to be redeclared in a child class. For the HttpFoundation example above, I believe that this property should be turned into a constant.

@stof
Copy link
Member

stof commented Oct 20, 2021

I agree with @derrabus here. That DebugClassLoader warning probably requires an opt-in, as the DebugClassLoader does not apply only on code extending Symfony classes.

@nicolas-grekas
Copy link
Member Author

It all depends on the frequency of redeclaring a public/protected property. I don't have stats, but I would think this should be pretty uncommon. If that's the case, then I think we can still do it.

@derrabus
Copy link
Member

I've seen proprietary codebases where overriding a property with a value was a common extension point. That might be ugly design, but I don't think that our DebugClassLoader should force that opinion on existing codebases.

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Oct 20, 2021

DebugClassLoader doesn't trigger deprecations for classes in the same vendor. That should cover that.

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Feb 8, 2022

Please have a look at #45360 for non-static properties.

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Feb 8, 2022

For static properties in the Symfony codebase, here are the ones we need a plan for:

  • Symfony\Component\Validator\Constraint::$errorNames
  • Symfony\Component\Console\Command\Command::$defaultName
  • Symfony\Component\Console\Command\Command::$defaultDescription
  • Symfony\Component\Form\Test\FormPerformanceTestCase::$supportedFeatureSetVersion
  • Symfony\Component\Form\Tests\AbstractLayoutTest::$supportedFeatureSetVersion

@derrabus
Copy link
Member

derrabus commented Feb 8, 2022

  • Symfony\Component\Console\Command\Command::$defaultName
  • Symfony\Component\Console\Command\Command::$defaultDescription

Shall we deprecate those properties and tell people to use the attribute instead?

@nicolas-grekas
Copy link
Member Author

Yes! And we might consider using a private prop or an attribute for $errorNames.
Would you like to give it a try?

@derrabus
Copy link
Member

derrabus commented Feb 8, 2022

I'll look into the commands.

@derrabus
Copy link
Member

derrabus commented Feb 8, 2022

#45361

derrabus added a commit that referenced this issue Feb 8, 2022
…bus)

This PR was merged into the 6.1 branch.

Discussion
----------

[Console] Deprecate the `$defaultName` property

| Q             | A
| ------------- | ---
| Branch?       | 6.1
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | yes
| Tickets       | Part of #43600
| License       | MIT
| Doc PR        | TODO

Commits
-------

ca3458c Deprecate the $defaultName property
nicolas-grekas added a commit that referenced this issue Feb 9, 2022
…m form-related tests (nicolas-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

Remove $supportedFeatureSetVersion static properties from form-related tests

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

See #43600 (comment)

Commits
-------

6cf0c68 Remove $supportedFeatureSetVersion static properties from form-related tests
nicolas-grekas added a commit that referenced this issue Feb 10, 2022
…or of `Constraint::ERROR_NAMES` (nicolas-grekas)

This PR was merged into the 6.1 branch.

Discussion
----------

[Validator] Deprecate `Constraint::$errorNames` in favor of `Constraint::ERROR_NAMES`

| Q             | A
| ------------- | ---
| Branch?       | 6.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | yes
| Tickets       | -
| License       | MIT
| Doc PR        | -

On the road to #43600

The BC layer is a bit light, but since this property seems like a piece of declarative statement that should we accessed only through `Contraint::getErrorName()`, I suggest doing it this way, and improve only if/when we get feedback from userland about it.

Commits
-------

aed0b99 [Validator] Deprecate `Constraint::$errorNames` in favor of `Constraint::ERROR_NAMES`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants