G
G
Grigory Vasilkov2019-08-11 13:36:03
PHP
Grigory Vasilkov, 2019-08-11 13:36:03

Why, apart from the fact that “someone has already thought of it”, is it recommended to write a separate class for each action?

There is a complexity of the question, but, it was not easier to choose than simple or "stupid" in the list, sorry)
I still can't fully understand why the methods of the standard PHP exception, such, how can I say - inconvenient?
I have heard many opinions on this, but almost all of them are based on the fact that "people have already come up with, you just need to do as they have already come up with."
When I rely on this phrase, I remember thousands of libraries rewritten from scratch, because people washed down the lib, threw it into the network, and then - the community was fucked up there, here he just didn’t know and wanted to apply for a vacancy, here he didn’t consult with anyone, but here I just gave birth because I was tired.

standart:
throw new \HttpException500('Text'); // и array вообще нельзя
throw new \LogicException('Wtf? There is an ENGLISH string?'); // перевести? болт. array вообще нельзя
throw new \InvalidArgumentException('Wtf? There is an ENGLISH string?'); // перевести? болт. array вообще нельзя
throw new \MyLibrary\InvalidArgumentException('Wtf? There is an ENGLISH string?'); // перевести? болт. array вообще нельзя

Why is this not recommended?
throw (new \Ex(\MyLibrary\MyClass::ERR_NOT_FOUND))->data($array);
throw (new \Http(500))->data($array);
throw (new \Flash('validation.error', '@application.err.phrase', $placeholder1, $placeholder2))->data($array);
throw (new \Invalid('login', 'rule_login', $placeholder2))->data($array);

Realizing that the message itself is hardly necessary for the guys who monitor a thousand servers, then the idea comes to somehow use the standard exception
throw new \InvalidArgumentException(json_encode((array) $data));

in order to understand, in principle, at least what came where it went
. It's not so much about general knowledge, but about the fact that these exceptions need to be caught, and since catching them from the sources where I read occurs almost in the controller, which is a special case, then it turns out that I catch the same actions in different actions and every time I write "log. translate. show. hide" in each suko file.
At first I saw in the falcon, they took around the program and wrote a single trikatch that performs the function. If returned to false - it is considered that it was caught. But in any case, this does not allow you to return to the place where the program lay down, it ends, it's just not critical with this approach. Of the benefits, this makes it possible to hang several handlers a la event. Of the minuses - if an exception occurs again inside this event, then this time everything will fall. and with fatality.
It just worries me that the exception is thrown (can be thrown and will be thrown) by methods such as iterative traversal
foreach ($dto as $field => $value) {
  $this->processString($value); // @throws
  $this->processInt($value); // @throws
  $this->processArray($value); // @throws
}

Uncle Fowler, drowning for OOP and application architecture, when he was brought such words quickly found it. You say you are using the exceptions incorrectly (well, of course, we are wrong, but not the standard). Here it is necessary to do ErrorBag simply speaking an array with errors to collect.
Correctly. Only the program throws exceptions and it doesn’t have time for an array with errors finally. If all of a sudden somewhere - criticized on the floor of the screen ...
What Ivan Shumov explained to me yesterday (a very smart master of his craft, by the way, I rarely meet such):
1. logging systems collect logs by the name of the exception class in order to group them into some of their admin- panels, where in the drop-down list by class name you can somehow understand what happened
2. in the documentation there is a way to write @throws and, with a quick review of the papers, understand what is more careful, this throws an error and the program may crash
3. a point that is a bit incomprehensible to me - another system will send you an exception that you are not ready to process if you do it your way. it's not entirely clear how another script, not even that the system can send me an exception, if there are a lot of computers, then they exchange messages through the bass, and not by the exceptions
Can you explain to me, the fool?
In the best case, of course - how to make translations of exceptions without the need for a specific tricatche each time to write "translate translate translate", or at least simply - why the hell do they write a new class for each error? Previously, they did const ERR_NOT_FOUND, and you could return it, you want throw, you want it in ErrorBag - anywhere, the namespace was not needed because the errors were in the interface of the class itself that throws them.
Why suddenly classes flooded?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Daria Motorina, 2019-08-11
@gzhegow

What Ivan Shumov wrote (points 1, 2) is correct. It is always easier to delimit exception classes in advance than to separate them into a separate class and refactor everywhere when the project logic requires an individual try-catch. Normal libs/packages/frameworks inherit their actions from the standard php ones, you can always catch the global \Exception or another parent if you don't need such detailed handling for each case.

G
Grigory Vasilkov, 2019-09-19
@gzhegow

Looks like I found some convenient way to use them. I'll post it here if anyone needs it.
Firstly, there is a standard there is some kind of PSR where there are 8 classes of "danger" of errors. But when I see a classification into 8 types, it looks like "we'll do it just in case" - a person is not able to divide something into 8 types, he keeps no more than 7 things in his head (and this is very pumped - 7 things). It is impossible to determine which of the 8 types of error is the one that now occurred to me. Maybe someone wrote in a book, but in life I think he does not do that.
If errors can be divided into 8 degrees, then the speech here is not in degrees, but in priority. That is, \SplPriorityQueue with a priority number, which, in which case, you can always change, and see the difference in statistics over a period of time. In this case, 8 types mean something like color markers in production - "open the red box, put things in the blue box", only without coloring, but in general 8 is too much for an unambiguous definition, and enough for statistics, although at the same time not.
We divide the emerging jambs into:
1. notification of the developer that the program is a curve and so it should not have been
2. notification / redirection of the user
3. notification of other modules in neighboring folders that something happened that they could solve, but in alone
The first group mainly includes standard exceptions. We write a function

function a() : int
{
  return 'vasia';
}

Funkia returns not what was asked. The developer who makes based on your code should find out about this. The program should not start. A convenient way to do such checks is to write the following code:
function verifyEmail($email) : ? string
{
  if (filter_var($email, FILTER_VALIDATE_EMAIL)) return null;
  return __FUNCTION__ . ' fails: ' . $email;
}
// ... code
if ($err = verifyEmail(123)) throw new \UnexpectedValueException($err);

We return the error text if the check fails, we validate.
So, for example, you can check input parameters for your own type without doing the OOP heresy of sewing the check into the constructor and splitting the array into properties, each of which is a setter with a validator, and so on. minus the file and a bunch of logic. These errors sometimes require the output of additional information in the trace. And since the exception does not take data as an additional parameter, I recommend adding the `public function data(array $data))` functionality and in special cases calling throw (new MyException($err))->data($data); and then in the logs you can add this very $data without resorting to a dance with a tambourine. It is unlikely that a system administrator or devops will need it, but it will definitely be needed by someone who goes to fix the error. Again - there is a call tree in the exception and there are arguments there. But a couple of times, for reasons I do not understand - the puff does not leave everything there, what I expect to read there. In the same validation, one string arrives as an argument, if you display the entire tree, the log will be too huge. And if one line - then it will not say anything. To understand why a validation has broken, it is often necessary to see the entire input data dictionary.
In the second group, I included HTTP application errors, applications as things capable of receiving commands and responding to them. These are different redirects. These are 500 handmade codes. It's the lack of access rights. Anything that ends up with HTTPException or RedirectBack anyway. The program will start, but the error may be caused by something going wrong in the external environment - no access rights, or this piece of the program is now disabled. That is, this is not a cant of code, but a deliberately established prohibition. These errors most often need to be translated into another language or a stub written. These errors are usually thrown by the framework or application, and either have a namespace like that of the framework, or something like \App\HttpException;
To the third groupI've included bugs that require external dependencies. As for this group, I'm not sure yet, maybe it's because I misunderstood the first two. Suppose we have a user authorization module and a module for working with JWT tokens. That's when the module could not parse the JWT token - it should throw the error "I worked and decided that something went wrong, but then it's not my concern." JWT parsing performs a very narrow task - token parsing. You can’t stick an authorization module there as a dependency, it’s like putting a director under the control of an employee. You can try to NOT-throw this error by initiating a token check in the Authorization module in order to process it right there. But this is strange, because Authorization can be done in ten ways and each of them is a hardcode addiction - not very good. It is these errors that should have a namespace, because they will be caught and worked with, trying to drown them out. That is, at the module level, this is a critical error. And at the program level, this is a warning.
At the moment, I think this is the right approach. If I find something else I'll fix it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question