Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error handling - is this a decent pattern?

I'm a naughty programmer, and until now I haven't handled errors properly (e.g. just catching a java.lang.Exception, printing a debug message, and moving on). When I do "handle" them, it's simply been to shut the compiler up.

I've recently learned the error (haha) of my ways, and would like to start doing it right. So I'm researching it here and other places (via Google searches).

Suppose I have a block of code which does the following:

  ...  
x.method1(); //  throws ExceptionTypeA
  ...  
y.method2(); //  throws ExceptionTypeB
  ...  
z.method3(); //  throws ExceptionTypeC
  ...  
x.method4(); //  throws ExceptionTypeA (again)
  ...  

From what I've gathered, the proper way to handle this is:

try {
      ...  
    x.method1(); //  throws ExceptionTypeA
      ...  
    y.method2(); //  throws ExceptionTypeB
      ...  
    z.method3(); //  throws ExceptionTypeC
      ...    
    x.method4(); //  throws ExceptionTypeA (again)
      ...
} catch (ExceptionTypeA e) {
    //  do something about condition A
} catch (ExceptionTypeB e) {
    //  do something about condition B
} catch (ExceptionTypeC e) {
    //  do something about condition C
}

This seems pretty straightforward to me, but it seems to get messy when I have a long block of code which throws various errors throughout. I seem to wind up with just one giant try/catch around my whole method! The alternative seems to be:

try {
      ...  
    x.method1(); //  throws ExceptionTypeA
      ...
} catch (ExceptionTypeA e) {
    //  do something about condition A
}

try {
      ...  
    y.method2(); //  throws ExceptionTypeB
      ...
} catch (ExceptionTypeB e) {
    //  do something about condition A
}

try {
      ...  
    z.method3(); //  throws ExceptionTypeC
      ...
} catch (ExceptionTypeC e) {
    //  do something about condition C
}
try {
      ...  
    x.method4(); //  throws ExceptionTypeA
      ...
} catch (ExceptionTypeA e) {
    //  do something about condition A
}

This looks really nasty. In cases like this, I've considered doing something like the following:

private void doSomething() throws exceptionTypeA, exceptionTypeB, exceptionTypeC {
      ...  
    x.method1(); //  throws ExceptionTypeA
      ...  
    y.method2(); //  throws ExceptionTypeB
      ...  
    z.method3(); //  throws ExceptionTypeC
      ...  
    x.method4(); //  throws ExceptionTypeA (again)
      ...  

}

public void doSomething_andHandleErrors() {
    try {
        this.toSomething();
    } catch (ExceptionTypeA e) {
        //  do something about condition A
    } catch (ExceptionTypeB e) {
        //  do something about condition B
    } catch (ExceptionTypeC e) {
        //  do something about condition C
    }
}

... and then just calling doSomething_andHandleErrors(); from outside. Is this a 'good' practice? Am I falling into some anti-pattern?

Thanks!

like image 902
loneboat Avatar asked Jan 26 '12 15:01

loneboat


People also ask

Is error handling necessary?

As errors could be fatal, error handling is one of the crucial areas for application designers and developers, regardless of the application developed or programming languages used. In worst-case scenarios, the error handling mechanisms force the application to log the user off and shut down the system.

What is the benefit of error handling?

Error handling is important because it makes it easier for the end users of your code to use it correctly. Another important issue is that it makes your code easier to maintain.

What is meaning of error handling?

Error handling refers to the routines in a program that respond to abnormal input or conditions. The quality of such routines is based on the clarity of the error messages and the options given to users for resolving the problem.


3 Answers

The main difference between your first and second example is how you handle the error itself. Is it transactional? In your first example, y.method2() will not run if x.method1() throws an exception. In your second example, it is possible depending on what the error handling does.

Both of those are decent patterns, it's a matter of the business case required here. Do you want the exception to get passed to the caller so they can handle it? Do you want to do something else because of the error?

Also, do not forget the finally block. You'll want to make sure you use one if you're dealing with resource management (IO Streams, database connections, for example) so that you can do cleanup if necessary.

like image 52
Michael Avatar answered Oct 06 '22 06:10

Michael


The point of handling exceptions is that you should be able to proceed further even when you face an exception. The first way and the third way are basically the same. If an exception occurs in the method1() you will directly exit the entire parent method without even an attempt at executing method2() and others.. The second method may seem cluttered at first but is actually the way in which it should be done.

Even better than that would be to handle the exceptions that you expect it to throw in the method itself and return a sort of default value which will allow further execution without breaking business logic or cause inconsistency.

EDIT:

Example of advantage when using 2 method:

Suppose you're making a text parser and expecting a date in the format DD-MM-YYYY. But while parsing you find that you get date in the format DD-MON-YYYY. These type of parsing exceptions can be handled and still allow further execution.

like image 31
Varun Achar Avatar answered Oct 06 '22 06:10

Varun Achar


This really depends on where (on which level) you want to catch that exception.

A method that does throw an exception simply means that "I do not want to deal with this exception/problem, let anyone else catch" it. Clean code should come after this way of thinking; should I catch here or not...

In your last case if you throw again those exceptions, this would mean you will not need the objects x,y,z during error handling since they would most probably be out of scope.

like image 35
Serkan Arıkuşu Avatar answered Oct 06 '22 08:10

Serkan Arıkuşu