0

Imagine the following code as a part of some program (java):

function z(){
try{
  //some code here, that might throw exceptions.
}catch (SomeException | SomeOtherException e){
  //some exception handling here.
}

function y(){
  z();
}

function x(){
  y();
}

And imagine that functions x and y won't execute as intended if Exceptions SomeException or SomeOtherException are thrown within function z. We want to write our code such that functions x and y know that Exceptions were thrown in function z, and make them act accordingly. Whats the best way to do this?

function z() thrown FunctionZFailedException{
  try{
    //some code here, that might throw exceptions.
  }catch (SomeException | SomeOtherException e){
    throw new FunctionZFailedException();
  }
}

function y() throws FunctionYFailedException{
  try{
    z();
  }catch (FunctionZFailedException e){
    throw new FunctionYFailedException();
  }
}

function x(){
  try{
    y();
  }catch (FunctionYFailedException e){
   //Do something, like alerting user that something went wrong.
  }
}

Is this too excessive, that is declaring new exceptions with the sole purpose of "forwarding" other exceptions up to a higher level?

I think we could also just let SomeException and SomeOtherException fly up and catch them inside function x. But imo that might make up for less readable code,

for example if the exceptions caught in function z are SQLException and NoSuchAlgorithmException, and function y is a login() function. Then function x would try to call login(), and either catch a SQLException | NoSuchAlgorithmException, if the let those exceptions simply fly up to the highest level, or catch a LoginFailedException, if we catch each exceptions immediately, and have them throw new exceptions. It seems like catching a LoginFailedException makes for more readable code.

Imo both ways have their cons (less readable code vs introducing many exceptions) and I'm wondering how similar cases are usually handled by seasoned java programmers.

Any general thoughts on exceptions also appreciated thanks guys

Mavoor
  • 1
  • In most cases, you'll want to include the original exception ("cause"): `catch (FunctionZFailedException e){ throw new FunctionYFailedException( e ); }` – JimmyB Apr 19 '16 at 14:19

2 Answers2

1

when you look at your code (and the names of methods and exceptions) find out if the methods and their thrown exceptions are on the same abstraction Level.

If you have a getInputStream() method, then the appropriate exception would be an IOException. If you call that method in your getDatabaseConnection(), then you should catch the IOException and throw an SQLException. And if you need this method for your saveCustomerToDatabase() Method, then you should throw something like a ProcessFailedException.

I'm not a big fan of writing javadocs, but sometimes you should ask yourself: Would I be able to write good javadoc for this method and its exceptions in the same language (i.e. technical language, business language, etc.)? You'll have Trouble writing a javadoc for a saveCustomerToDatabase() -Method if it throws an IOException.

EasterBunnyBugSmasher
  • 1,507
  • 2
  • 15
  • 34
0

If you are happy with the current design of method z(), and you want methods y() and x() to "know" that something bad has happened in z(), then you can have z() rethrow the exception after swallowing it.

public void z() {
    try {
        // some code here, that might throw exceptions.
    } catch (SomeException | SomeOtherException e) {
        // handle the exception and then rethrow it
        logger.log("An exception happened in z().");
        throw e;
    }
}

public void y() {
    try {
        z();
    } catch(Exception e) {
        // handle problem with z() and rethrow the exception
        logger.log("An exception happened when calling z().");
        throw e;
    }
}

public void x() {
    try {
        y();
    } catch(Exception e) {
        // handle problem with y()
        logger.log("An exception happened when calling y().");
    }
}
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360