Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid duplicating complicated catch blocks

Tags:

java

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);
}
like image 276
mxcl Avatar asked Feb 16 '10 12:02

mxcl


People also ask

How do you avoid code duplication?

Don't Repeat Yourself (DRY): Using DRY or Do not Repeat Yourself principle, you make sure that you stay away from duplicate code as often as you can. Rather you replace the duplicate code with abstractions or use data normalization. To reduce duplicity in a function, one can use loops and trees.

Is duplicating code bad?

It's safe to say that duplicate code makes your code awfully hard to maintain. It makes your codebase unnecessary large and adds extra technical debt. On top of that, writing duplicate code is a waste of time that could have been better spent.


2 Answers

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).

like image 128
p.marino Avatar answered Sep 17 '22 23:09

p.marino


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);
    }
}  
like image 37
BalusC Avatar answered Sep 21 '22 23:09

BalusC