Hi
On 4/30/25 13:18, Derick Rethans wrote:
- Exceptions MUST NOT be ``final``.
Could the RFC explain why not?
I'm not sure if this is useful to add to the RFC itself as a “only extra
explanation” and since the discussion is an equally official resource:
The reason is to allow flexible extensions of the exception hierarchy,
e.g. when adding a more specific type of exception to provide further
context to some parent exception that just identifies some “concept”.
A HTTP request can fail (HttpRequestFailedExceptions) for different
reasons, e.g. due to a connection failure (ConnectionFailedException) or
due to a server error (ServerErrorException). Now we might also want to
clarify why the connection failed. It could be a timeout
(ConnectionTimeoutException) or DNS resolution error
(DnsResolutionFailedException). This already requires several of the
exceptions not to be final to allow extending them. Making the leaf
exceptions final would not bring any value and just cause additional
churn when realizing that having more child exceptions would be helpful
to the user. Also some extension might intentionally want to allow
subclassing for some classes. When subclassing a class it also makes
sense being able to subclass the corresponding exceptions. I have made
it legal to throw “unowned” exceptions when subclassing something in:
https://github.com/php/policies/pull/17/commits/1a125dabea93b4c919677065651c4fdea1b035e3
- The name of the extension SHOULD NOT be used as a prefix or suffix of
the unqualified class name of additional exceptions.
Could you add an example of how to do it instead (or a "not this" "but
that" example)?
I've expanded on this paragraph and added an example in:
https://github.com/php/policies/pull/17/commits/c0e8891fc9a7a459a26a990b33108bfbd5ae3311
Basically the intention is to avoid class names “oddly specific” names
that just concatenate some random words. Ideally the class name would be
a succinct English phrase that matches what you would communicate them
to a co-worker. I would say “The HTTP request failed”, but not “The HTTP
request that we perform using the network request library called curl
failed”. Or I would say “The timezone is invalid” rather than “The
timezone, which relates to the concept called ‘date’ (and not any other
use of the term timezone) is invalid”.
How exactly that works in practice greatly depends on the extension,
that's why it's just a SHOULD (NOT). I trust that folks make good
choices when they have a reminder to make a good choice.
- Any two exceptions with different causes MUST be identifiable either
by a unique exception class name, a stable ``$code``, or a
class-specific additional property suitable for programmatic
consumption (e.g. an enum).
I would probably not even allow the stable ``$code`` in here, as I have
seen from experience people don't really check for them.
My goal here is to avoid making exception messages part of the backwards
compatibility promise. Whether or not the `$code` is useful in practice
will be something that folks can figure out when writing an RFC. It
probably greatly depends on the type of extension what makes sense.
Perhaps it would also make sense to officially widen the code from `int`
to `int|string|UnitEnum` to avoid the PDO gotcha. Since `__construct()`
does not participate in LSP checks and since `getCode()` is already
final, this seems safe to me.
Best regards
Tim Düsterhus