Capture and treatment of exceptions in a generic way

Asked

Viewed 167 times

3

In general the most common is to capture the exceptions specific and do some treatment with it, right?

Example:

try
{
   //Algum trecho de código
}
catch (MyException myException)
{
   //Especifico para este erro
}
catch (Exception ex)
{
   //Qualquer outra coisa
}

However, when the programmer does not create a catch specific to your Exception, she ends up being captured by Exception generic.

Example:

try
{
   //Algum trecho de código
}
catch (Exception ex)
{
   //Se aqui a exception fosse uma instancia de MyException
   //o programador não teria acesso à dados importantes da outra exception
   //a menos que ele fizesse uma conversão
   //mas como ele não sabia que poderia ocorrer este erro, não o fez.
}

This ends up giving problems, because in some cases, it is recorded log of these exceptions in a table in the database, and the information is not complete...

The right thing in these cases would be to implement the catch specific, in this regard there is no doubt.

But here comes the doubt, is there any way to mitigate this problem? Some good practice?

What came to mind, would implement a class that dealt with each of the Exception, so I could call a specific method via Reflection. Behold:

Class:

public static class ExceptionHandler
{
    public static void Handle(this MyException exp)
    {
      //Aqui faço alguma coisa
    }

    public static void Handle(Exception ex)
    {
       //Aqui outra
    }
}

Use of it:

try
{
   //Algum trecho de código
}
catch (Exception ex)
{
    var baseType = ex.GetType();
    var convertedExp = Convert.ChangeType(ex, baseType);
    var methodInfo = typeof(ExceptionHandler).GetMethod("Handle", new Type[1] { baseType });
    methodInfo.Invoke(convertedExp, new object[1] { convertedExp });
}

I don’t think it’s a good idea and maybe I don’t even have much to do...

What can be said about this?

  • your question doesn’t make much sense, there are dozens of classes that extend Exception in the language, not having a custom Exception doesn’t necessarily mean leaving it to Exception Generico, another thing, launching an Exception is a hell of a costly process, if you can avoid, avoid

1 answer

3


I haven’t seen such an important question on the site in a long time.

In general the most common is to capture the specific exceptions and do some treatment with it, right?

If it makes sense in that scenario, it’s yes.

However, when the programmer does not create a catch specific to your Exception, she ends up being captured by Exception generic.

This ends up giving problems, because in some cases is recorded log of these exceptions in a table in the database, and the information is not complete...

Not necessarily, that’s a possibility. If you have a specific one and a generic one together, there’s a chance that there’s something wrong there.

In the specific place the common is to have specific treatments. For generic treatments the place is usually more general.

What came to mind was to implement a class that dealt with each of the Exception, so I could call a specific method via Reflection.

There are several ways to do it, almost nobody runs away from rice and beans because it is not usually necessary.

Even you may not use exception in your API and avoid as far as you give exceptions in the third party API (even the .NET), it has advantages.

I don’t think it’s a good idea and maybe I don’t even have much to do... What do you think?

I saw no advantage in doing exactly like this, in fact it seems a great gambit not to be thinking about the specific solution. It’s not C’s philosophy#.

So it seems more suitable (I’m not saying it’s ideal for any case):

catch (MyException ex) {
    ex.Handle();
}

If you want you can have others catches, including of Exception *if it makes sense), but do so explicitly, even if they all have identical codes inside (I doubt why some of these methods will receive parameters). It may seem that these repetitions are a violation of DRY, but DRY is not that.

try {
    //Algum trecho de código
} catch (MyException myException) {
    ex.Handle();
} catch (Exception ex) {
    ex.Handle();
}

Despite ex seems to be the same code looking at the syntax, its semantics is different because they are of different types.

Having canonical information on how to manipulate an exception is not only good, but also fundamental. Wrong are people who repeat the same manipulation throughout the code. But only the call is normal.

I just don’t think it’s ideal to use reflection. Almost always using reflection is doing something wrong to save typing or do gambiarra to solve a problem that did not actually exist.

You can do with switch. It should be used as a Pattern matching very simply, the compiler deals right to you without reflection. I will not show because it is still wrong, is to change a form of switch that has appropriate consequences for the situation by another that works, but creates some problems for some scenarios (that was even the reason they have created such filter exceptions).

The catch has always been a form of Pattern matching with a more specialized semantics.

And of course, if you have any case that manipulation should behave differently from the pattern you created in your class that centralizes manipulations, you should treat that. Then there must be a different version than Handle(MyException). It needs to be a method that manipulates this same exception but in a different way:

public static void Handle(this MyException exp) {
    //Aqui faço alguma coisa
}
public static void Handle(this MyException exp, string message) {
    //Aqui faço alguma coisa
}
public static void HandleSpecific(this MyException exp) {
    //Aqui faço alguma coisa
}

I put in the Github for future reference.

You could also have a parameter that indicates what to do and internally you will have a switch deciding what to do (using Pattern matching). Or there may be other mechanisms, I’m just giving examples of how to treat this situation.

Many will say that you should not centralize this and have a class of manipulation for every exception you treat, and it has its meaning there, I just don’t think it should be like this forever. But a lot of good people do it because in most scenarios it’s not a problem. I will not dwell on this because it is not the focus, there are other discussions about it on the site and elsewhere, this is orthogonal to what is asked here.

Developing software is more complicated than it seems

That’s what I always say, to make all the right decisions you need to understand all the development concepts and combine them all in the right way in each case. It’s very complicated to do that, a lot of things are not orthogonal.

I am of the opinion that the exceptions should almost necessarily have a standard manipulation, but this is not how it happened in any language, I understand why (but has solution to the problem that would be this), but has better solutions. I won’t stretch out either.

Apart from the exception, it is something that is quite basic, there was a time when almost every programmer knew how to make the abstraction and generalization of an action into a function. Today people learn by cake recipe, so they read a tutorial that talks to do in a very simple way, without thinking about all the consequences, without worrying about the concrete case, about the interactions of that mechanism with others, and then one learns wrong. And it makes a wrong code that other people will use as a reference, and maybe it makes another wrong tutorial or book or video. There comes a point where the person doesn’t even realize that he is teaching wrong. It’s like Covid-19. Contaminates so many people that right begins to be considered wrong by many.

That’s why I talk to learn in a structured way. I have several answers here, especially about exceptions. If you read them in isolation, you’ll learn wrong. It was not my intention, but the answer was isolated to that question, not to everything I needed to learn about it. Until now had no question about what was posted here, no one learned anything about the DRY of exceptions manipulations.

Note that this answer does not give all possible information on the subject because the question is not about that, but shows the importance of not repeating code manipulation when it is equal. There are other points to look at here, don’t take the answer as a definitive guide on how to deal with it. And read several other answers on the subject.

Completion

I think you should forget this idea of always just capturing Exception. But it’s a solution, it’s creative, if done right I don’t think it’s unviable, it’s just not ideal.

  • Really, I think the most appropriate solution would be the one you gave there. And with regard to everything else, it was very enlightening. Thank you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.