Skip to content

[HttpFoundation] Deprecate extending some methods #19734

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
Sep 14, 2016

Conversation

GuilhemN
Copy link
Contributor

@GuilhemN GuilhemN commented Aug 25, 2016

Q A
Branch? "master"
Bug fix? no
New feature? no
BC breaks? no
Deprecations? yes
Tests pass? yes
Fixed tickets #19727
License MIT
Doc PR

It's really hard to change methods signature because of bc. I'm proposing to deprecate extending some getters/setters of Response because of this (and because extending them is not really useful).
If you like this approach it could be used in other places to simplify bc in 4.0.

Edit: This causes issues (warnings always triggered) when mocking Response entirely but does it matter as people should only mock needed methods?


// Deprecations
$class = get_class($this);
if (__CLASS__ === $class || 0 === strpos($class, 'Symfony\\')) {
Copy link
Contributor Author

@GuilhemN GuilhemN Aug 25, 2016

Choose a reason for hiding this comment

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

should we hardcode a list here to improve performance?

Copy link
Member

Choose a reason for hiding this comment

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

ok for me. what about this µoptim:?
if (__CLASS__ === $class || 'S' !== $class[0] || 0 === strpos($class, 'Symfony\\Component\\')) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any vendor not beginning by S would pass the check. I'll try hard-coding a list.

return;
}

foreach (array('setDate', 'setExpires', 'setLastModified', 'getDate', 'getExpires', 'getLastModified') as $method) {
Copy link
Member

Choose a reason for hiding this comment

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

array should be moved to a private static

private static $deprecatedMethods = array('setDate', 'setExpires', 'setLastModified', 'getDate', 'getExpires', 'getLastModified');
private static $deprecationsTriggered = array(
__CLASS__ => true,
ApacheRequest::class => true,
Copy link
Member

Choose a reason for hiding this comment

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

this is Request, not Response :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, I really need an autocompleter... :P

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well in fact that's request, it just shouldn't be here... ^^

@stof
Copy link
Member

stof commented Aug 25, 2016

Regarding mocks, could we skip the warning for common mocking libraries ? At least PHPunit_MockObject and Prophecy are easy to detect, as their doubles are implementing an interface (\PHPUnit_Framework_MockObject_MockObject for PHPUnit and \Prophecy\Doubler\DoubleInterface for Prophecy). I don't know Mockery, but it may be the same.

This would avoid causing issues for people mocking the Response class for other methods (Prophecy does not allow doing partial mocking for instance).

@symfony/deciders what do you think ?

@GuilhemN GuilhemN force-pushed the RESPONSE branch 2 times, most recently from 0ce0f25 to 270a0cf Compare August 25, 2016 16:53
@GuilhemN
Copy link
Contributor Author

GuilhemN commented Aug 25, 2016

@stof fixed using get_parent_class when necessary. For Mockery it looks like its mocks aren't extending the mocked class so it won't change anything.


self::$deprecationsTriggered[$class] = true;
foreach (self::$deprecatedMethods as $method) {
$m = new \ReflectionMethod($class, $method);
Copy link
Member

Choose a reason for hiding this comment

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

$m should be $r "as usual"

Copy link
Contributor Author

@GuilhemN GuilhemN Aug 25, 2016

Choose a reason for hiding this comment

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

isn't $r for ReflectionClass?

Copy link
Member

Choose a reason for hiding this comment

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

I'd be $c then :) $r is for Reflector, the base interface

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed makes sense now ^^

fabpot added a commit that referenced this pull request Aug 25, 2016
…etick)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle][Security] Remove useless mocks

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

Removes mocks causing issues in #19734.

Commits
-------

fcd3345 [FrameworkBundle][Security] Remove useless mocks
symfony-splitter pushed a commit to symfony/framework-bundle that referenced this pull request Aug 25, 2016
…etick)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle][Security] Remove useless mocks

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

Removes mocks causing issues in symfony/symfony#19734.

Commits
-------

fcd3345 [FrameworkBundle][Security] Remove useless mocks
symfony-splitter pushed a commit to symfony/security-http that referenced this pull request Aug 25, 2016
…etick)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle][Security] Remove useless mocks

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

Removes mocks causing issues in symfony/symfony#19734.

Commits
-------

fcd3345 [FrameworkBundle][Security] Remove useless mocks
symfony-splitter pushed a commit to symfony/security that referenced this pull request Aug 25, 2016
…etick)

This PR was merged into the 2.7 branch.

Discussion
----------

[FrameworkBundle][Security] Remove useless mocks

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

Removes mocks causing issues in symfony/symfony#19734.

Commits
-------

fcd3345 [FrameworkBundle][Security] Remove useless mocks
@nicolas-grekas
Copy link
Member

rebase unlocked

@GuilhemN
Copy link
Contributor Author

@nicolas-grekas i already removed these commits.

@javiereguiluz
Copy link
Member

@Ener-Getick could we estimate the performance hit related to the code added in the Response class (if any)? Thanks!

@GuilhemN
Copy link
Contributor Author

@javiereguiluz that's hard to benchmark but when I run ResponseTest in different conditions, I have no significant results (maybe a difference of 1 or 2ms and it originally took ~50ms).

@nicolas-grekas
Copy link
Member

👍 nice trick for eventually fixing these type hints in 4.0.
performance shouldn't be an issue: the new code is quick, and Response aren't instantiated that often.

@GuilhemN
Copy link
Contributor Author

GuilhemN commented Sep 1, 2016

At the same time, would you like to make final other methods of Response?

I think we can make final those methods:

  • setContent/getContent
  • setProtocolVersion/getProtocolVersion
  • setStatusCode/getStatusCode
  • setCharset/getCharset
  • setPrivate/setPublic
  • getAge
  • getMaxAge/setMaxAge
  • setSharedMaxAge
  • getTtl/setTtl
  • setClientTtl
  • getEtag/setEtag
  • hasVary/getVary/setVary
  • isInvalid/isSuccessful/isRedirection/isClientError/isServerError
  • isOk/isForbidden/isNotFound/isRedirect/isEmpty

Or is that too much? I think we can deprecate extending most methods and see if people complain about some deprecations. It won't break any applications and would make bc easier if this methods actually aren't extended (which should be the case as their content is very generic).

@fabpot
Copy link
Member

fabpot commented Sep 1, 2016

The Response object is a data object that should be very "stable" (as HTTP is stable). So, I would say that extending most of the methods do not make sense indeed... if someone needs to do that, it's probably a bug that we should fix instead.

@GuilhemN
Copy link
Contributor Author

GuilhemN commented Sep 1, 2016

Ok, done.
The following methods will still be extendable (if you think we should also deprecate extensing some of them):

  • create
  • __clone
  • prepare
  • send/sendHeaders/sendContent
  • isCacheable/isFresh
  • isValidateable/mustRevalidate
  • expire
  • setCache
  • setNotModified/isNotModified
  • closeOutputBuffers
  • ensureIEOverSSLCompatibility (maybe this one should be made @internal)

Edit: we can't deprecate extending setContent and getContent as they are extended in symfony's specialized responses.

@jakzal
Copy link
Contributor

jakzal commented Sep 2, 2016

@Ener-Getick setContent() is also overridden by laravel. Before proceeding with this PR, we should check if there are any popular libraries extending methods you propose to make final.

@GuilhemN
Copy link
Contributor Author

GuilhemN commented Sep 2, 2016

Sure i don't think i'll have the time this week-end but maybe next week.

@@ -186,6 +186,15 @@ class Response
511 => 'Network Authentication Required', // RFC6585
);

private static $deprecatedMethods = array('setDate', 'getDate', 'setExpires', 'getExpires', 'setLastModified', 'getLastModified', 'setProtocolVersion', 'getProtocolVersion', 'setStatusCode', 'getStatusCode', 'setCharset', 'getCharset', 'setPrivate', 'setPublic', 'getAge', 'getMaxAge', 'setMaxAge', 'setSharedMaxAge', 'getTtl', 'setTtl', 'setClientTtl', 'getEtag', 'setEtag', 'hasVary', 'getVary', 'setVary', 'isInvalid', 'isSuccessful', 'isRedirection', 'isClientError', 'isOk', 'isForbidden', 'isNotFound', 'isRedirect', 'isEmpty');
Copy link
Member

Choose a reason for hiding this comment

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

could you put this array on several lines to ease reading please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 done

@nicolas-grekas
Copy link
Member

I'm 👍 with the updated list

@fabpot
Copy link
Member

fabpot commented Sep 14, 2016

Thank you @Ener-Getick.

@fabpot fabpot merged commit c0a26bc into symfony:master Sep 14, 2016
fabpot added a commit that referenced this pull request Sep 14, 2016
…r-Getick)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[HttpFoundation] Deprecate extending some methods

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

It's really hard to change methods signature because of bc. I'm proposing to deprecate extending some getters/setters of `Response` because of this (and because extending them is not really useful).
If you like this approach it could be used in other places to simplify bc in 4.0.

Edit: This causes issues (warnings always triggered) when mocking `Response` entirely but does it matter as people should only mock needed methods?

Commits
-------

c0a26bc [HttpFoundation] Deprecate extending some methods
@fabpot
Copy link
Member

fabpot commented Sep 14, 2016

@Ener-Getick What about doing the same with the Request class?

@GuilhemN GuilhemN deleted the RESPONSE branch September 15, 2016 05:28
@GuilhemN
Copy link
Contributor Author

GuilhemN commented Sep 15, 2016

I have to take a look at it to see if that's worth it, i'll probably do that in a few days.

@GuilhemN
Copy link
Contributor Author

As a side node I searched methods extended in drupal and laravel and I only found setContent and sendContent, so no problem with this PR.

@fabpot fabpot mentioned this pull request Oct 27, 2016
fabpot added a commit that referenced this pull request Jan 15, 2017
…DebugClassLoader - prepare making some classes final (GuilhemN)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Debug] Trigger deprecation on `@final` annotation in DebugClassLoader - prepare making some classes final

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

BC promises become quickly huge but making classes `final` can limit these promises.
At the same time, many classes of the symfony codebase are not meant to be extended and could be  `final`; that's the goal of this PR: prepare making them final in 4.0 by triggering deprecations in their constructor:
```php
public function __construct()
{
    if (__CLASS__ !== get_class($this)) {
        @trigger_error(sprintf('Extending %s is deprecated since 3.3 and won\'t be supported in 4.0 as it will be final.', __CLASS__), E_USER_DEPRECATED);
    }
}
```

I updated two classes for now but we can do much more if you like it.

Commits
-------

c2ff111 [Debug] Trigger deprecation on `@final` annotation in DebugClassLoader
fabpot added a commit that referenced this pull request Jan 30, 2017
…grekas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[HttpFoundation] Mark more methods as `@final`

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

Follow up of #19734 (ping @GuilhemN)

Commits
-------

84a664f [HttpFoundation] Mark more methods as `@final`
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.

7 participants