Reputation: 26883
I have this code:
try {
do_stuff();
return do_more_stuff();
} catch (UnsupportedEncodingException e) {
throw CustomException.programmer_error(e);
} catch (ProtocolException e) {
throw CustomException.programmer_error(e);
} catch (MalformedURLException e) {
throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
throw new CustomException(e);
} catch (IOException e) {
throw CustomException.unexpected_error(e);
}
I now need to have all those catch blocks in another similar function. What is the best way to avoid duplication here?
Note that the code inside the two try blocks is not very similar.
Also I can't really put the set of catches higher up.
Note, I'd prefer to avoid:
try {
do_stuff();
return do_more_stuff();
} catch (Exception e) {
handle_exception_via_rtti(e);
}
Upvotes: 19
Views: 3418
Reputation: 8358
How about introducing a generic Action class that can be subclassed:
public class Action {
public void runWithHandlers() throws Exception {
try {
run();
} catch (UnsupportedEncodingException e) {
throw CustomException.programmer_error(e);
} catch (ProtocolException e) {
throw CustomException.programmer_error(e);
} catch (MalformedURLException e) {
throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
throw new CustomException(e);
} catch (IOException e) {
throw CustomException.unexpected_error(e);
}
}
public void run() throws Exception {
// TODO subclasses of Action must implement this
}
}
Then somewhere else in your code you instantiate one of the subclasses of Action and call runWithHandlers():
new MyAction().runWithHandlers();
Upvotes: 1
Reputation: 22660
If you can afford Scala, check it out: you can pattern match the exception in the catch block. See Scala for Java Refugees Part 4: Pattern Matching and Exceptions.
Upvotes: 0
Reputation: 1108782
Note, I'd prefer to avoid:
Then either just live with it, or wait until JDK7 comes with Multicatch so that you can rewrite like:
try {
do_stuff();
return do_more_stuff();
} catch (UnsupportedEncodingException | ProtocolException | MalformedURLException e) {
throw CustomException.programmer_error(e);
} catch (SocketTimeoutException e) {
throw new CustomException(e);
} catch (IOException e) {
throw CustomException.unexpected_error(e);
}
You can alternatively also move this into the constructor of CustomException
and do a (nasty) global catch, but then you'll need to add a bunch of (nasty) if/else
blocks to determine the type of the exception cause. All with all, I'd just prefer to stick with the way as you already did.
Update: another alternative is to split/refactor the lines which can potentially throw the exception as separate tasks into another method blocks throwing CustomException
. E.g.
try {
do_stuff_with_encoding();
do_stuff_with_url();
do_stuff_with_ws();
// ...
return do_more_stuff();
} catch (SocketTimeoutException e) {
throw new CustomException(e);
} catch (IOException e) {
throw CustomException.unexpected_error(e);
}
...
public SomeObject do_stuff_with_encoding() throws CustomException {
try {
do_stuff();
} catch (UnsupportedEncodingException e) {
throw CustomException.programmer_error(e);
}
}
public SomeObject do_stuff_with_url() throws CustomException {
try {
do_stuff();
} catch (MalformedURLException e) {
throw CustomException.programmer_error(e);
}
}
public SomeObject do_stuff_with_ws() throws CustomException {
try {
do_stuff();
} catch (ProtocolException e) {
throw CustomException.programmer_error(e);
}
}
Upvotes: 5
Reputation:
It depends of why the do_stuff
and do_more_stuff
throw the checked exceptions. Are they doing that to force the user to treat the exception? If yes, then you trying to avoid:
try {
do_stuff();
return do_more_stuff();
} catch (Exception e) {
handle_exception_via_rtti(e);
}
is a good thing.
If your code just catches Exception
, and the do_stuff
and do_more_stuff
later add extra exceptions, you'll probably never know about the change and the fact that your code could now be wrong.
So you might have to deal with throwing the kitchen sink and treat all those exceptions, unless the methods could switch to unchecked exceptions.
On the other hand, if the methods are throwing checked exceptions just because the programmer was lazy in treating with them and just wanted to pass the buck, maybe you are looking at this from the wrong angle.
Upvotes: 2
Reputation: 6252
Personally I'd try to make the
do_stuff();
return do_more_stuff();
part conform to a more general format in order to apply Strategy (as a pattern).
Then you can refactor all the places where you call this kind of block so that they can call a more generalized block (where the catches are laid out just once).
Upvotes: 8