Re: Feature request: https://github.com/php/php-src/issues/13301
| From: | Robert Landers | Date: | Wed, 07 Feb 2024 11:57:57 +0000 |
| Subject: | Re: Feature request: https://github.com/php/php-src/issues/13301 | ||
| References: | 1 2 3 4 5 6 7 8 9 10 11 12 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-122326@lists.php.net to get a copy of this message | ||
On Wed, Feb 7, 2024 at 11:27 AM Григорий Senior PHP / Разработчик Web
<6562680@gmail.com> wrote:
>
> Yes, that was the second build of the error bag I presented in the github ticket.
> First one was a Trait that added an error bag as property in class and returned an array with
> two results.
>
> The trouble was you have to refactor all places you used your function doesn't matter,
> want you or not.
>
> And the last build just collects errors to the global stack of error bags allowing you to stay
> untouched by the existing code.
>
> Of course, if code should start to return null/null-object as result - you have to implement
> that (refactoring the places where null is inapplicable), but error collection itself won't
> change existing code then, it works like an observer pattern now.
>
> ср, 7 февр. 2024 г. в 13:21, Robert Landers <landers.robert@gmail.com>:
>>
>> 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
>>
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: https://www.php.net/unsub.php
>>
>
>
> --
> +375 (29) 676-48-68 / Mobile - предпочитаемый способ связи
> https://t.me/gzhegow /
> https://t.me/%2B375296764868 / Telegram
> 6562680@gmail.com
Please don't top-post your replies. It's very rude.
If it's just syntax around arrays, it's something that doesn't require
much (if any refactoring)
$result = getResult();
could be seen by PHP as the same as
[$result] = getResult();
Allowing you to implement things as fast or as slow as you wanted to,
or ignore errors completely.
Robert Landers
Software Engineer
Utrecht NL