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

Skip to content

[DX] Fix phpdoc for serializer normalizers exceptions #22231

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

Closed
wants to merge 1 commit into from

Conversation

Nek-
Copy link
Contributor

@Nek- Nek- commented Mar 31, 2017

The normalizers throw exceptions. They need to be documented for DX in the normalizer/denormalizer interfaces.

Q A
Branch? master (rebase on 2.7 if you want?)
Bug fix? no
New feature? yes?
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #22218
License MIT
Doc PR Not needed

@carsonbot carsonbot added Status: Needs Review DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature labels Mar 31, 2017
@syrm
Copy link

syrm commented Mar 31, 2017

Exceptions are a BC Break.
Imagine, i using an object which implements NormalizerInterface, i never implemented a try catch, because interface don't throw exception.

Some implementations of the interface may have returned a null or empty value because exceptions are not allowed. Suddenly a new version allow exception in interface, so lots of implementations can change their mind and throw an exception. That break my code.

@Nek-
Copy link
Contributor Author

Nek- commented Mar 31, 2017

This PR doesn't actually break backward compatibility, it just fix the PHPDoc.

@Nek- Nek- force-pushed the fix/serializer-phpdoc-exception branch from cb1e746 to f05d0ed Compare March 31, 2017 12:17
@syrm
Copy link

syrm commented Mar 31, 2017

You fix the PHPDoc on an interface, so my comment is valid.
You add a new output (exception).

* @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException
* @throws \Symfony\Component\Serializer\Exception\ExtraAttributesException
* @throws \Symfony\Component\Serializer\Exception\LogicException
* @throws \Symfony\Component\Serializer\Exception\RuntimeException
Copy link
Member

Choose a reason for hiding this comment

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

We are using use statements instead of FQCN.

Copy link
Member

Choose a reason for hiding this comment

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

Also, we don't document exceptions if we don't also add when this can be thrown.

Copy link

Choose a reason for hiding this comment

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

exception should ALWAYS be in PHPDoc, you can't know when an interface throw an exception or not and you can't work properly with interface when you don't know that.

Copy link

@folliked folliked Mar 31, 2017

Choose a reason for hiding this comment

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

where is the rule to specify the exception for doc in the interface ??? This is specific logic exception, not business exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fabpot that's a good point. I'll document the "why" exceptions are used for. Currently, it's not easy to get it at first glance.

Copy link
Contributor

Choose a reason for hiding this comment

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

you can't know when an interface throw an exception or not

Interfaces don't throw exceptions, their implementations do. I disagree with putting them into interface, because when you make different implementation which don't throw those exceptions, you are not respecting the interface. Interface specifies what class implementing it MUST implement. I don't see a need here to force the implementation to use these exceptions

Copy link

Choose a reason for hiding this comment

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

throwing an exception is not a mandatory when you implement an interface. For a simple reason, exception is not a mandatory output, it can happen, or not.

@theofidry
Copy link
Contributor

A user shouldn't catch LogicExceptions, so you should not need to document them: they are sign that you need to fix something in your code (usually configuration related).

@syrm
Copy link

syrm commented Apr 2, 2017

Arguments is in interface ?
Yes.
Because you must can call any implementation of interface without change your code.

Return is in interface ?
Yes.
Because you must can get result of any implementation of interface without change your code.

We have put return in PHPDoc ?
Yes.
Because before PHP7 it's impossible to know the return of interface without PHPDoc
With PHP7 you can ommit this because you can put the return in the code of interface.

Why exceptions must be un PHPDoc for an interface so ?
Because :
You can't put them in the code (like Java).
You should manage any exception throw pas any implementation of interface without change your code.
But :
An implementation have no obligation to throw any exception that was in interface
But :
An implementation must not throw any exception not declared in interface, that's gonna break code.

@syrm
Copy link

syrm commented Apr 2, 2017

@theofidry that's not always true.
Imagine you're on a website and on the right column you have secondary information. When the database for this right column is temporary down you get the exception "DatabaseDown" you still want render the page and you put for the right column "Not available" instead of making an error 500. But a new implementation throw sometimes "DatabaseOffline" you code don't know that, that was not on interface and you get suddenly an error 500.

@theofidry
Copy link
Contributor

@syrm which is why PDOException is a RuntimeException, not a LogicException: failure to connect to a database may be an acceptable scenario for which your application should not crash.

It's not an absolute rule, but if you were to compare it to Java that's the would somewhat translate to a compilation error and runtime errors. It's just that in PHP we don't have this compilation step.

@syrm
Copy link

syrm commented Apr 2, 2017

DatabaseOffline can be a LogicException, you don't know.
Look here : https://www.reddit.com/r/PHP/comments/63119v/exception_should_always_be_documented_with_phpdoc/

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Apr 3, 2017

To me, we just need a single line in the phpdoc, using a use statement of course:
@throws \Symfony\Component\Serializer\Exception\ExceptionInterface

@nicolas-grekas
Copy link
Member

Should be applied on 2.7 also.

@nicolas-grekas nicolas-grekas added this to the 2.7 milestone Apr 3, 2017
@theofidry
Copy link
Contributor

If you are going to add them then you are missing a few places:

  • src/Symfony/Component/Serializer/Encoder/DecoderInterface.php
  • src/Symfony/Component/Serializer/Encoder/EncoderInterface.php
  • src/Symfony/Component/Serializer/Normalizer/DenormalizableInterface.php
  • src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php
  • src/Symfony/Component/Serializer/SerializerInterface.php

@dunglas
Copy link
Member

dunglas commented Apr 3, 2017

+1 for @nicolas-grekas' solution

@fabpot
Copy link
Member

fabpot commented Apr 3, 2017

What would be the benefit to add those generic exceptions? I'm 👎

@syrm
Copy link

syrm commented Apr 4, 2017

If you don't want a generic exception you should rewrite the existing exception because they're very specialized :

+     * @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException
+     * @throws \Symfony\Component\Serializer\Exception\ExtraAttributesException
+     * @throws \Symfony\Component\Serializer\Exception\LogicException
+     * @throws \Symfony\Component\Serializer\Exception\RuntimeException

@Nek-
Copy link
Contributor Author

Nek- commented Apr 9, 2017

@nicolas-grekas disagree. Most of the classes I modify doesn't even exist in 2.7. I also disagree with adding a standard exception in phpdoc because to me the PHPDoc would be useless (and this PR would also be). You can choose to just close it if you think so.

I fixed the FQCN, and added a note for cases when exceptions are throw.

Please notice that there is a problem of coherence of throwed exceptions...

@@ -27,6 +34,13 @@
* @param array $context options available to the denormalizer
*
* @return object
*
* @throws BadMethodCallException Occurs when the normalizer is not call in an expected context
Copy link
Member

Choose a reason for hiding this comment

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

[...] is not called [...]

* @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data
* @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data
* @throws LogicException Occurs when the normalizer is not supposed to denormalize
* @throws RuntimeException Occurs if the class cannot be instantiate
Copy link
Member

Choose a reason for hiding this comment

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

instantiated

@@ -26,6 +30,11 @@
* @param array $context Context options for the normalizer
*
* @return array|scalar
*
* @throws InvalidArgumentException Occurs when the object given is not an attempted type for the normalizer
* @throws CircularReferenceException Occurs when the normalizer detect a circular reference when no circular
Copy link
Member

Choose a reason for hiding this comment

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

detects

* @throws InvalidArgumentException Occurs when the object given is not an attempted type for the normalizer
* @throws CircularReferenceException Occurs when the normalizer detect a circular reference when no circular
* reference handler can fix it
* @throws LogicException Occurs when the normalizer is not call in an expected context
Copy link
Member

Choose a reason for hiding this comment

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

called

@NoiseByNorthwest
Copy link

@syrm unrecoverable exceptions (i.e. without code patch) like Runtime|Logic hierarchies or implementation specific exceptions should not be part of the interface IMHO

@syrm
Copy link

syrm commented Apr 21, 2017

It should @NoiseByNorthwest INPUT/OUTPUT is the part of contract.

@NoiseByNorthwest
Copy link

@syrm have fun with all of your interfaces bloated with irrelevant Runtime|Logic like exceptions....

@syrm
Copy link

syrm commented Apr 21, 2017

@NoiseByNorthwest so interface are bad written and we should continue like this ?

@theofidry
Copy link
Contributor

@syrm what's the point of documenting an exception that is only here to tell you you didn't configure something properly? Your application should not have to deal with them, only you. If you have an edge case where you need that, they you can always catch \Exception or \Throwable and do what you want. As it would probably be something very specific it's likely to be dependent of the implementation, hence you check the actual code behind not a contract that anyone can violate.

@syrm
Copy link

syrm commented Apr 21, 2017

You know the contract of an interface can't be incomplete because you think there is not interest to have a complete contract.

And as a developer I won't put a try catch \Exception everywhere because developer are too lazy to describe the contract of interface fully.

Then, a wrong configuration can happen only on production and when it's an optional part a webpage you don't want crash the full page.

@theofidry
Copy link
Contributor

It's not a lack of interest in a complete contract, it's that it's different contracts for different targets. A \RuntimeException is for the application, which may handle it whereas \LogicException is for you as a developer. Ensuring that you don't get a \LogicException when running your application in production is your responsibility.

So it's not laziness in the contract description, it's you trying to tweak the contract to use it differently than it's meant to be. You're free to add yourself more work and ensure to have contracts which can be tweaked that way, but don't blame people if they want to be more pragmatic and not take care of this.

But if you're not sensible to those arguments let's change the angle and see it the other way around: bring a case where adding those elements to the contract are meaningful. If there is a point, I'm sure no one here will disagree with adding those exceptions to the doc. It's just that as it is now it doesn't provide anything than additional noise and/or confusion.

@syrm
Copy link

syrm commented Apr 21, 2017

RuntimeException is also for developer. Throw new RuntimeException("can't connect to database myprivatedatabase"). When you don't catch this sensitive information can be shown on you page. Every exception is for developer because it can crash your application when you don't handle it.

Add these information don't add additional noise or confusion. And when it add noise or confusion that mean this exception is useless or not specific. So you should rethink your interface to remove these exception or rewrite them.

@NoiseByNorthwest
Copy link

NoiseByNorthwest commented Apr 21, 2017

Here is the problem, you dont get RuntimeException semantic. A database connection error is not a RuntimeException because its origin is not necessarily a program flaw.

The normalizers throw exceptions. They need to be documented for DX
in the normalizer/denormalizer interfaces.

[Serializer] fit Symfony phpdoc standard

It also adds meaning of each exception throw.

Fix grammary in phpdoc
@Nek- Nek- force-pushed the fix/serializer-phpdoc-exception branch from af10b21 to 836759b Compare April 25, 2017 05:49
@Nek-
Copy link
Contributor Author

Nek- commented Apr 25, 2017

@xabbuh 👍

@fabpot
Copy link
Member

fabpot commented Jul 6, 2017

Thank you @Nek-.

fabpot added a commit that referenced this pull request Jul 6, 2017
…ek-)

This PR was submitted for the master branch but it was merged into the 3.2 branch instead (closes #22231).

Discussion
----------

[DX] Fix phpdoc for serializer normalizers exceptions

The normalizers throw exceptions. They need to be documented for DX in the normalizer/denormalizer interfaces.

| Q             | A
| ------------- | ---
| Branch?       | master (rebase on 2.7 if you want?)
| Bug fix?      | no
| New feature?  | yes?
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #22218
| License       | MIT
| Doc PR        | Not needed

Commits
-------

ec3cc84 Fix phpdoc for serializer normalizers exceptions
@fabpot fabpot closed this Jul 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature Status: Needs Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.