On Mon, Oct 17, 2022, at 12:33 PM, Tim Düsterhus wrote:

>>> Okay, now the Exception message changed. Personally I do not consider
>>> this a BC break: I believe Exception messages are meant for human
>>> consumption, not for programs. Otherwise fixing a typo in the message
>>> would be a BC break. If the code wants to learn about the cause, it
>>> should either use the '$code' or different types of Exception should be
>>> thrown to clarify the cause by entering a different catch() block.
>>>
>> 
>> Yes, the specific error message should be part of the BC promise. This
>> allows building test suites that can assert the message in a stable way.
>
> I'm not talking about test suites here. I believe makes sense to verify 
> the error message to ensure a specific error message is emitted to the 
> human observer in the error log.
>
> I was talking about code that does something like this, which I consider 
> to be inherently unsafe:
>
> try { … }
> catch (SomeException $e) {
>    if ($e->getMessage() === 'Foobar') doSomething();
>    else doSomethingElse();
> }
>
> As a library author I want to be able to provide the best possible 
> Exception message to ease debugging for the user. This is not possible 
> if I am locked into a bad choice forever.

Just to be clear, such code is sometimes necessary.  If the exception doesn't 
include sufficient information as dedicated properties, parsing out the string 
becomes the only option.  I've had to do this myself.

In 100% of cases, without exception (no pun intended), that's because the code 
that throws the exception is bad and wrong and should be fixed.  But such code 
absolutely exists in the wild, including in php-src.  I recently needed to 
sscanf() and then explode the message of \ArgumentCountError as that was the 
only way I could find to get the class/method names out of it.  I died inside a 
little.

So yes, such code is inherently unsafe, but is sadly not as uncommon as it 
should be.

All that said, I agree that we have not and should not treat error message 
strings as part of the API guarantee.  If anything, maybe that will help 
incentivize people to stop writing bad (unparsable) exceptions.

Which I think gets at the crux of the issue here, and what is often the issue 
in BC discussions.

PHP does not, and has never, guaranteed full BC for all code.  It has tried 
very hard to maintain BC for "well-behaved code."  Well-behaved code can 
generally update to a new version, even a new major, very easily with minimal 
work.  Any deprecations are alerted at least a year in advance, sometimes 
several, and usually have easy-to-automate transitions that tools like Rector 
can implement.  (The discussion about deprecations being "too noisy" in some 
tooling is another matter that has been hashed out before, so I won't belabor 
it here.)  Code that is following common best-practices rarely has an issue.

The problem is that "well-behaved" is not well-defined.  Is relying on an error 
message string well-behaved?  I'd argue no, but as noted above sometimes 
there's no better option.  Others may disagree.  Is relying on the exact 
exception class thrown well-behaved?  Well... sometimes.  Is relying on an 
error condition being swallowed rather than turning into an exception 
well-behaved?  I could argue either way here, honestly.  Is code relying on 
undefined variables silently becoming null well-behaved?  Absolutely not, and 
hasn't been for a decade, but it wasn't until PHP 8.0 that the language called 
people out for it by default, so many projects had a lot of catch up to do.  
(Eg, I did that catch up for TYPO3.)

I don't know that we can make a clear definition of "well-behaved" that 
everyone could agree on.  It would be nice, but it's a very squishy topic.  But 
it may be prudent, when not tied down to this specific RFC, to have a broader 
discussion about better codifying (meaning, writing down) what we consider a BC 
break and what we don't, what some heuristics are for "well-behaved," and so 
on.  That could help avoid, or at least shorten, a lot of discussions in the 
future.

--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to