On Tue, Feb 6, 2024 at 9:22 PM Larry Garfield <la...@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