简体   繁体   中英

Code refactoring via handling exceptions in different method

I have 2 methods like below in a class

// this method doesn't return anything.
void X(){
  try{operation1}
  catch(SpecificException1 e1){do something}
  catch(SpecificException2 e2){do something}
  catch(SpecificException3 e3){do something}
}

// this method return an object.
Object Y(){
  try{operation2}
  catch(SpecificException1 e1){do something}
  catch(SpecificException2 e2){do something}
  catch(SpecificException3 e3){do something}
  return object;
}

I tried to refactor it in the following way:

// this method doesn't return anything.
void X(){
  try{operation1}
  catch(Exception e){handle(e)}
}

// this method return an object.
object Y(){
  try{operation2}
  catch(Exception e){handle(e)}
  return object;
}
handle(Exception e){
  try{ throw e}
  catch(SpecificException1 e1){do something}
  catch(SpecificException2 e2){do something}
  catch(SpecificException3 e3){do something}
  catch(Exception e){do something}
}

But I told that catching general exception is not a good code practice as I am catching general exception in methods X and Y. But as per my thought process though I am catching general exception in X and Y methods, I am handling specific exception in "handle" method which is catching specific exception.

I am not able to get what's wrong with this approach. In my opinion it is adding little bit more readability in the code. Doing same catching in individual method will make code little bit less readable. this will get more tedious if I have 3-4 methods having same type of catching in the class.

If you have different approach handling this type of situation please suggest that.

A much better solution would be to define a generic functional Command interface and pass that to a method that would execute the command and deal with exceptions:

public interface Command<R> {
    R execute() throws SpecificException1, SpecificException2, SpecificException3;
}

...

public void x() {
    this.execute(() -> operation1());
}

public SomeObject y() {
    return this.execute(() -> operation2()).orElse(someDefaultValue);
}

private <R> Optional<R> execute(Command<R> command) {
    try {
        return Optional.ofNullable(command.execute()); 
    }
    catch(SpecificException1 e) {
        doSomething();
    }
    catch(SpecificException2 e) {
        doSomethingElse();
    }
    catch(SpecificException3 e) {
        doYetAnotherThing();
    }
    return Optional.empty();
}

Of course this should be adapted to your actual use-case. It looks weird to me to ignore exceptions. if you actually want to propagate them, you wouldn't need this optional stuff, and each exception handling method would simply throw a runtime exception for example.

If you throw a exception you either catch it or throw it. Besides the missing ';' this would not compile because your handle-method throws a unspecific exception that is not concidered by any catch block.

to make this run you would have to add a catch-block for a unspecific exception, but then you are going to swoallow any other exception as well.

the other way would be to declare that handle throws Exception but then you have to handle this unspecific exception in your methods X and Y again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM