On Wed, Feb 7, 2024 at 11:27 AM Григорий Senior PHP / Разработчик Web <6562...@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.rob...@gmail.com>: >> >> 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 >> > > > -- > +375 (29) 676-48-68 / Mobile - предпочитаемый способ связи > https://t.me/gzhegow / https://t.me/%2B375296764868 / Telegram > 6562...@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 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php