Re: Feature request: https://github.com/php/php-src/issues/13301
| From: | Robert Landers | Date: | Wed, 07 Feb 2024 10:21:05 +0000 |
| Subject: | Re: Feature request: https://github.com/php/php-src/issues/13301 | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-122324@lists.php.net to get a copy of this message | ||
On Tue, Feb 6, 2024 at 9:22 PM Larry Garfield <larry@garfieldtech.com> wrote:
>
> On Tue, Feb 6, 2024, at 7:56 PM, Григорий Senior PHP / Разработчик Web
> wrote:
> > Thanks Larry, I will read both articles next weekend.
> >
> > Am not even talking about changing
throw to
> > raise.
> >
> > Am talking only about:
> > - production ready code
> > - that should be able to refactor with error collectors (that was not
> > implemented years ago)
> > - without touching return types
> > - without touching input arguments of existing code
> > - without possible code fall after throw exception: you have to try/catch
> > all places you use that function (sometimes you predict possible error, and
> > yes, write return class/enum to extend/refactor it later)
> > (and yes, if old code did not support returning null/null-object before -
> > you have to refactor return types then)
> >
> > While working with queues you have a list of tasks
> > - then you reduce it to smaller with reducer (unique/filter/merge)
> > - then do some queries
> > - then walk initial data using reduced results: copying reports to save
> > errors/warnings to each task separately
> >
> > It cannot be solved with exceptions. In addition, large arrays throw
> > exceptions that cause timeloss. It's definitely not a tool for.
> > Also your method could return many errors (today - only one
> > error/exception), and you need to write a second method, then call the
> > second method, then debug the second method.
> >
> > So what's in rest? Arrays collection of warnings and errors. Changing
> > return types or passing second-return by reference.
> >
> > [ Enum case ~ DTO output ] covers newly written code. Old code is
> > uncovered. You have to rewrite a full tree, that's why some trick is
> > necessary.
> >
> > I did it my way with an error bag stack. I enable it inside the function or
> > in place I call the function. I want to share this experience, and imagined
> > it would be better for all users. It could be done without 2 classes, 10
> > functions and work with push/pop/current (closer to ob_start/ob_get_clean
> > story).
> > I guess it could be implemented if raise world will put
> > any data to the
> > current error bag in the stack. Exactly if the current error bag is present
> > (declared manually like you can declare() strict types or ticks for some
> > scope).
> >
> > I agree that there's more mandatory problems to solve that I didn't even
> > know about.
> > I tried to talk about error handling with a few developers, all of them
> > recommend:
> > 1. Use exceptions, don't make anything fresh
> > 2. Do validation at the script start to reduce the count of errors later
> >
> > I've just encountered cases where bugs come from within - once you
> > integrate a really bad external system with its own checks, which are
> > described in hundreds of documents, I'm sure you'll encounter new bugs once
> > the "working" code is released to production. And then you will need to
> > quickly and easily reorganize it.
> >
> > And you can't.
> > And you will be sad.
> > And, "PHP moves differently" is a completely wrong principle, I believe in
> > "watching for".
> I think there's a subtle but important difference here between what you're describing
> as the problem and what you implied the solution was (which I then ran with).
>
> What you're talking about is trying to change the error handling model of existing code
> without changing function signatures. There are only two possible ways to do that, both of them
> bad: Unchecked exceptions and globals.
>
> What I described, based on the syntax you offered, is checked exceptions, which necessarily
> means changing the function signature. Error handling is part of the contract of a function. If
> its error handling changes, it *should* have a signature change to indicate that. (That unchecked
> exceptions do not do that is the problem with unchecked exceptions.) So if "no changes to
> existing code" is the goal, checked exceptions as I describe them are not the answer you are
> looking for.
>
> It seems from your latest message that you're describing more a generalized version of
> json_last_error() and similar functions. The problem there is that
> such an API design is generally considered very poor practice outside of C, because it's all
> necessarily based on globals and "hope you remembered to check the thing that no one told you
> to check and is not even slightly obvious to check". That is not something I would want better
> support for in the language at all. There's probably cleaner ways to emulate it in user-space,
> but that is for a particular application to sort out. There's definitely cleaner monadic
> solutions (which I've written before and are quite neat) using a writer/logger monad, but that
> again doesn't meet your "don't change existing code" requirement. I don't
> think anything the language can do will meet that requirement and be a good design.
>
> --Larry Garfield
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
Oh wow, this conversation got really interesting while I was asleep :D
I think this could actually be interesting in a
semi-backwards-compatible way, by just adding some syntax sugar:
function getResult(): ?Result, ?ResultError {
if($error) return null, $error;
}
instead of, but this would still work when destructuring:
function getResult(): array {
if($error) return [null, $error);
}
This would still work (the "backwards compatible" part):
[$result, $error] = getResult();
or this:
$result, $error = getResult();
Essentially, return types with a comma are just a "strongly typed
array" and a comma on the left-hand side of assignment is just a
destructure.
Robert Landers
Software Engineer
Utrecht NL