In a current Java project we have code similar to the following example:
try {
doSomeThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
try {
doOtherThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
// ... some more calls to different method ...
try {
finallyDoYetSomethingCompletelyDifferent(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
As you can see, several different method are called with the exact same object and for every call the same exception is caught and handled the same (or in a very similar) way. The exception is not re-thrown, but may only be logged and then discarded.
The only reason why there is a try-catch
around every single method, is to always execute all of the methods, no matter if a previously executed method failed.
I don't like the above code at all. It takes up a lot of space, is very repetitive (especially the logging done in the catch
-block; not presented here) and just looks bad.
I can think of some other ways to write this code, but don't like them very much, either. The following options came to my mind:
Loop-switch sequence / for-case paradigm
(See Wikipedia or The Daily WTF)
for (int i = 0; i <= 9; i++) {
try {
switch (i) {
case 0:
doSomeThing(anObject); break;
case 1:
doOtherSomeThing(anObject); break;
// ...More cases...
case 9:
doYetSomethingCompletelyDifferent(anObject); break;
}
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
}
This is obviously bad code, very error-prone and looks amateurish.
Reflection
Use reflection to get Method
objects for the methods to call and store them in a list in the order they are supposed to be executed. Then iterate over this list and call the method using anObject
as only parameter. The exception is handled inside of the loop.
I don't like this approach, as bugs (for example typos in the method names) only pop up during runtime and the Reflection API is somewhat chatty.
Functor
Create a Functor class like this:
private class Functor
{
void doStuff(MyObject object) throws SameException;
}
Then create a list of Functor
objects that call the methods. Like this:
List<Functor> functors = new ArrayList<Functor>();
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doSomeThing(anObject);
}
});
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doOtherSomeThing(anObject);
}
});
Later, iterate this list and call execute()
on every Functor
object.
I can summarize my feeling about this approach with two words: Code bloat.
As I don't really like all four approaches, I would like to discuss this problem here. What do you feel is the best approach? How did you solve similar problems in the past? Is there maybe a much simpler solution I missed completely?
Resuming the program When a checked/compile time exception occurs you can resume the program by handling it using try-catch blocks. Using these you can display your own message or display the exception message after execution of the complete program.
You can either use the try-catch-finally approach to handle all kinds of exceptions. Or you can use the try-with-resource approach which allows an easier cleanup process for resources.
When an exception is thrown the method stops execution right after the "throw" statement. Any statements following the "throw" statement are not executed.
I would advocate the refactoring approach (or "Why did we get here in the first place?"):
Consider why the individual methods can throw the exception after doing "stuff" with myObject and that exception can then be safely ignored. Since the exception escapes the method, myObject must be in an unknown state.
If it's safe to ignore the exception, surely it must be the wrong way to communicate that something went wrong in each method.
Instead, maybe it's each method that needs to do some logging on failure. If you don't use static loggers, you can pass a logger to each method.
The functor approach is the nicest one to my mind - it's just a shame that Java doesn't have a nicer way of representing closures or delegates. That's basically what you're really after, and in C# (and many other languages) it would be trivial.
You can cut down on the physical bloat somewhat by using something like:
Functor[] functors = new Functor[] {
new Functor() { @Override public void execute(MyObject anObject) {
doSomeThing(anObject);
}},
new Functor() { @Override public void execute(MyObject anObject) {
doSomeOtherThing(anObject);
}}
};
The whitespace collapsing here may well be against the style guide you're using, but I think it makes the code easier to actually read, in that you can see the meat more easily.
Better start lobbying for closures in Java 8 ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With