"switch" equivalent for exception handling - java

This is not a question about exception handling in general, but it applies specifically end exclusively to the use of some frameworks. A few examples of typical starting points:
GWT: public void onFailure(Throwable caught) implementation of the AsyncCallback interface.
JAX-RS: public Response toResponse(E throwable) implementation of the ExceptionMapper<E extends Throwable> interface.
Both the above methods receive an instance of Throwable. Normally, I've seen developers use a simple "if/else if" block to differentiate the handling logic:
// As specified by the AsyncCallback class of the GWT framework
public void onFailure(Throwable caught) {
if (caught instanceof AnException) {
// handle AnException
} else if (caught instanceof AnotherException) {
// handle AnotherException
} else if (caught instanceof YetAnotherException) {
// handle YetAnotherException
} else if (caught instanceof ...) {
// and so on...
}
}
Since I am not a fan of "if/else if" blocks for many reasons, I came up with the following "pattern" which converts the "if/else if" block into a "try/catch" block, behaving as if it were a "switch" block:
public void onFailure(Throwable caught) {
try {
throw caught;
} catch(AnException e1) {
// handle AnException
} catch(AnotherException e2) {
// handle AnotherException
} catch(YetAnotherException e3) {
// handle YetAnotherException
} catch(...) {
// and so on...
}
}
My question is: Are there any drawbacks - in terms of performance, best practices, code readability, general safety, or just anything else I'm not considering or noticing - using this approach?

Using exceptions to direct program flow under normal circumstances is a code smell, but that's not really what you're doing here. I think you can get away with this for a few reasons:
We already catch and re-throw exceptions for all manner of reasons (e.g., "catch, take some action, propagate"). This is a bit different in intent, but it's no worse in terms of cost.
You've already incurred the cost of this exception being thrown at least once. You've possibly incurred the cost of its causes being thrown, caught, and wrapped or re-thrown. The cost of filling in the stack traces has already been paid. Re-throwing an already-populated exception one more time is not going to increase the order of complexity.
You are not using exceptions to direct the flow of the normal code path. You're reacting to a error, so you are already on the exceptional path, and you should rarely (if ever) end up here. If this pattern is inefficient, it will hardly matter unless you are encountering lots of exceptions, in which case you have bigger problems. Spend your time optimizing the paths you expect to take, not the ones you don't.
Aesthetically, there are few things that make my skin crawl like long chains of if/else if blocks, especially when the conditions are merely type-checking. What you're proposing is, in my opinion, far more readable. Having multiple, ordered catch clauses is common, so the structure is mostly familiar. The try { throw e; } preamble may be unorthodox, but it's easy enough to reason about.
Just be wary when propagating Throwable. Some errors, like the VirtualMachineError hierarchy, are a sign that something has gone horribly wrong, and they should be allowed to run their course. Others, like InterruptedException, communicate something about the state of the originating thread, and they should not be blindly propagated on a different thread. Some, like ThreadDeath, span both categories.

Performance would only matter if there are a huge amount of errors thrown. It doesn't impact the performance in the success case. There being so many errors would be much more of an issue than the time is takes to process them.
If you call a local method, and it throws an exception, then it would be fine to use catch blocks to process it. This is doing the same but with remote methods. It's not normal control flow because an exception has already been thrown from the RPC call before getting to the method, so it's fine to use the usual exception handling constructs.
There are some checks that can be done by the compiler, like checking that the most specific exceptions are listed first, but the use of the general Throwable type loses some type safety. This is unavoidable because of the framework.
I would be fine with either example here, as it doesn't make much of a difference.

The two blocks of code you show are actually superficially very similar: they are both the same "shape" to my eye at first glance.
And it's worth noting that the if/else chain is actually fewer lines of code and more immediately comprehensible than the try/catch version.
I don't think the try/catch version is wrong per se, but when compared side by side like this I don't see any reason why it would be better either.
And all else being equal, uncontroversial code is always better than controversial code: you never want a reader of your code to be distracted away from what your code is doing by how you've chosen to do it.

Related

Throwing a new exception while throwing an old exception

If a destructor throws in C++ during stack unwinding caused by an exception, the program terminates. (That's why destructors should never throw in C++.) Example:
struct Foo
{
~Foo()
{
throw 2; // whoops, already throwing 1 at this point, let's terminate!
}
};
int main()
{
Foo foo;
throw 1;
}
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
If a finally block is entered in Java because of an exception in the corresponding try block and that finally block throws a second exception, the first exception is silently swallowed. Example:
public static void foo() throws Exception
{
try
{
throw new Exception("first");
}
finally
{
throw new Exception("second");
}
}
public static void main(String[] args)
{
try
{
foo();
}
catch (Exception e)
{
System.out.println(e.getMessage()); // prints "second"
}
}
This question crossed my mind: Could a programming language handle multiple exceptions being thrown at the same time? Would that be useful? Have you ever missed that ability? Is there a language that already supports this? Is there any experience with such an approach?
Any thoughts?
Think in terms of flow control. Exceptions are fundamentally just fancy setjmp/longjmp or setcc/callcc anyway. The exception object is used to select a particular place to jump to, like an address. The exception handler simply recurses on the current exception, longjmping until it is handled.
Handling two exceptions at a time is simply a matter of bundling them together into one, such that the result produces coherent flow control. I can think of two alternatives:
Combine them into an uncatchable exception. It would amount to unwinding the entire stack and ignoring all handlers. This creates the risk of an exception cascade causing totally random behavior.
Somehow construct their Cartesian product. Yeah, right.
The C++ methodology serves the interest of predictability well.
You can chain exceptions. http://java.sun.com/docs/books/tutorial/essential/exceptions/chained.html
try {
} catch (IOException e) {
throw new SampleException("Other IOException", e);
}
You can also have a try catch inside your finnally too.
try{
}catch(Exception e){
}finally{
try{
throw new SampleException("foo");
}catch(Exception e){
}
}
Edit:
Also you can have multiple catches.
I don't think multiple exceptions would be a good idea, because an exception is already something you need to recover from. The only reason to have more than one exception I can think of is if you use it as part of your logic (like multiple returns), wich would be deviating from the original purpose of the idea of the Exception.
Besides, how can you produce two exceptions at the same time?
Could a programming language handle multiple exceptions? Sure, I don't see why not. Would this be useful? No, I would say it would not be. Error handling and resumption is very hard as it is - I don't see how adding combinatorial explosion to the problem would help things.
Yes, it is possible for a language to support throwing multiple exceptions at a time; however, that also means that programmers need to handle multiple exceptions at a time as well, so there is definitely a tradeoff. I have heard of languages that have this although I am having trouble coming up with the list off the top of my head; I believe LINQ or PLINQ may be one of those languages, but I don't quite remember. Anyway, there are different ways that multiple exceptions can be thrown... one way is to use exception chaining, either by forcing one exception to become the "cause" or "previouslyProgatingException" of the other, or to bottle all of the exceptions up into a single exception representing the fact that multiple exceptions have been thrown. I suppose a language could also introduce a catch clause that lets you specify multiple exception types at once, although that would be a poor design choice, IMHO, as the number of handlers is large enough as is, and that would result in an explosion of catch clauses just to handle every single possible combination.
C++ std::exception_ptr allows you store exceptions. So it should be possible to embed exceptions in other exceptions and give you the impression that you have the stack on thrown exceptions. This could be useful if you want to know the root cause of the actual exception.
One situation where multiple thrown exceptions in parallel might be useful, is unit testing with JUnit:
If a test fails, an exception is thrown (either produced by code under test or an assertion).
Each #After method is invoked after the test, whether the test fails or succeeds.
If an After method fails, another exception is thrown.
Only the exception thrown in the After method is displayed in my IDE (Eclipse) for the test result.
I know that JUnit notifies its test listeners about both exceptions, and when debugging a test in Eclipse I can see the first exception appearing in the JUnit view, only to be replaced by the second exception shortly after.
This problem should probably be resolved by making Eclipse remember all notifications for a given test, not only the last one. Having "parallel exceptions", where the exception from the finally does not swallow the one from the try, would solve this issue too.
If you think about it, the situation you've described has Exception("First") as the root cause of Exception("second"), conceptually. The most useful thing for the user would probably be to get a stack dump showing a chain in that order...
In managed platforms, I can think of situations where it might be useful to have a disposer "elevate" an exception to something which is stronger, but not totally fatal to an application. For example, a "command" object's disposer might attempt to unwind the state of its associated connection to cancel any partially-performed commands. If that works, the underlying code may attempt to do other things with the connection. If the attempted "cancel" doesn't work, the exception should probably propagate out to the level where the connection would have been destroyed. In such a case, it may be useful for the exception to contain an "inner exception", though the only way I know to achieve that would be to have the attempted unwinding in a catch block rather than a "finally" block.

Handling multiple exceptions

I have written a class which loads configuration objects of my application and keeps track of them so that I can easily write out changes or reload the whole configuration at once with a single method call. However, each configuration object might potentially throw an exception when doing IO, yet I do not want those errors to cancel the overall process in order to give the other objects still a chance to reload/write. Therefore I collect all exceptions which are thrown while iterating over the objects and store them in a super-exception, which is thrown after the loop, since each exception must still be handled and someone has to be notified of what exactly went wrong. However, that approach looks a bit odd to me. Someone out there with a cleaner solution?
Here is some code of the mentioned class:
public synchronized void store() throws MultipleCauseException
{
MultipleCauseException me = new MultipleCauseException("unable to store some resources");
for(Resource resource : this.resources.values())
{
try
{
resource.store();
}
catch(StoreException e)
{
me.addCause(e);
}
}
if(me.hasCauses())
throw me;
}
If you want to keep the results of the operations, which it seems you do as you purposely carry on, then throwing an exception is the wrong thing to do. Generally you should aim not to disturb anything if you throw an exception.
What I suggest is passing the exceptions, or data derived from them, to an error handling callback as you go along.
public interface StoreExceptionHandler {
void handle(StoreException exc);
}
public synchronized void store(StoreExceptionHandler excHandler) {
for (Resource resource : this.resources.values()) {
try {
resource.store();
} catch (StoreException exc) {
excHandler.handle(exc);
}
}
/* ... return normally ... */
]
There are guiding principles in designing what and when exceptions should be thrown, and the two relevant ones for this scenario are:
Throw exceptions appropriate to the abstraction (i.e. the exception translation paradigm)
Throw exceptions early if possible
The way you translate StoreException to MultipleCauseException seems reasonable to me, although lumping different types of exception into one may not be the best idea. Unfortunately Java doesn't support generic Throwables, so perhaps the only alternative is to create a separate MultipleStoreException subclass instead.
With regards to throwing exceptions as early as possible (which you're NOT doing), I will say that it's okay to bend the rule in certain cases. I feel like the danger of delaying a throw is when exceptional situations nest into a chain reaction unnecessarily. Whenever possible, you want to avoid this and localize the exception to the smallest scope possible.
In your case, if it makes sense to conceptually think of storing of resources as multiple independent tasks, then it may be okay to "batch process" the exception the way you did. In other situations where the tasks has more complicated interdependency relationship, however, lumping it all together will make the task of analyzing the exceptions harder.
In a more abstract sense, in graph theory terms, I think it's okay to merge a node with multiple childless children into one. It's probably not okay to merge a whole big subtree, or even worse, a cyclic graph, into one node.

Which is better/more efficient: check for bad values or catch Exceptions in Java

Which is more efficient in Java: to check for bad values to prevent exceptions or let the exceptions happen and catch them?
Here are two blocks of sample code to illustrate this difference:
void doSomething(type value1) {
ResultType result = genericError;
if (value1 == badvalue || value1 == badvalue2 || ...) {
result = specificError;
} else {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
}
callback(result);
}
versus
void doSomething(type value1) {
ResultType result = genericError;
try {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
} catch (ExceptionType e) {
result = specificError;
} finally {
callback(result);
}
}
On the one hand, you're always doing a comparison. On the other hand, I honestly don't know what the internals of the system do to generate an exception, throw it, and then trigger the catch clause. It has the sound of being less efficient, but if it doesn't add overhead in the non-error case, then it's more efficient, on average. Which is it? Does it add similar checking anyway? Is that checking there in the implicit code added for exception handling, even with the additional layer of explicit checking? Perhaps it always depends on the type of exception? What am I not considering?
Let's also assume that all "bad values" are known -- that's an obvious issue. If you don't know all the bad values -- or the list is too long and not regular -- then exception handling may be the only way, anyway.
So, what are the pros and cons of each, and why?
Side questions to consider:
How does your answer change if the value is "bad" (would throw an exception) most of the time?
How much of this would depend on the specifics of the VM in use?
If this same question was asked for language-X, would the answer be different? (Which, more generally, is asking if it can be assumed checking values is always more efficient than relying on exception handling simply because it adds more overhead by current compilers/interpreters.)
(New) The act of throwing an exception is slow. Does entering a try block have overhead, even if an exception is not thrown?
Similarities on SO:
This is similar to the code sample in this answer, but states they are similar only in concept, not compiled reality.
The premise is similar to this question but, in my case, the requester of the task (e.g. "Something") isn't the caller of the method (e.g. "doSomething") (thus no returns).
And this one is very similar, but I didn't find an answer to my question.
And similar to far too many other questions to list, except:
I'm not asking about theoretical best practice. I'm asking more about runtime performance and efficiency (which should mean, for specific cases, there are non-opinion answers), especially on resource limited platforms. For instance, if the only bad value was simply a null object, would it be better/more efficient to check for that or just attempt to use it and catch the exception?
"How does your answer change if the value is "bad" (would throw an exception) most of the time?" I think that's the key right there. Exceptions are expensive as compared to comparisons, so you really want to use exceptions for exceptional conditions.
Similarly, your question about how this answer might change depending on the language/environment ties into that: The expense of exceptions is different in different environments. .Net 1.1 and 2.0 are incredibly slow the first time an exception is thrown, for instance.
Purely from an efficiency standpoint, and given your code examples, I think it depends on how often you expect to see bad values. If bad values are not too uncommon, it's faster to do the comparison because exceptions are expensive. If bad values are very rare, however, it may be faster to use the exception.
The bottom line, though, is that if you're looking for performance, profile your code. This block of code may not even be a concern. If it is, then try it both ways and see which is faster. Again, it depends on how often you expect to see bad values.
I could find surprisingly little current information about the cost of throwing Exceptions. Pretty obviously there must be some, you are creating an object, and probably getting stack trace information.
In the specific example you talk about:
if (value1 == badvalue || value1 == badvalue2 || ...) {
result = specificError;
} else {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
}
The problem for me here is that you are in danger if (probably incompletely) replicating logic in the caller that should be owned by the method you are calling.
Hence I would not perform those checks. Your code is not performing an experiment, it does "know" the data it's supposed to be sending down I suppose? Hence the likelyhood of the Exception being thrown should be low. Hence keep it simple, let the callee do the checks.
In my opinion you should have try/catch blocks around anything that could potentially throw exceptions, if only to have a safe running system. You have finer control of error responses if you check for possible data errors fist. So I suggest doing both.
Well, exceptions are more expensive, yes but for me, its about weighting the cost of efficiency vs bad design. unless your use case demands it, always stick to the best design.
the question really is, when do you throw an exception? in exceptional situations.
if your arguments are not in the range that you're looking for, i'd suggest returning an error code or a boolean.
for instance, a method,
public int IsAuthenticated(String username, String password)
{
if(!Validated(username,password)
{
// just an error
// log it
return -2;
}
// contacting the Database here
if cannot connect to db
{
// woww this is HUUGE
throw new DBException('cannot connect'); // or something like that
}
// validate against db here
if validated, return 0;
// etc etc
}
thats my 2 cents
My personal opinion is that exceptions indicate that something is broken - this might well be an API called with illegal arguments or division by zero or file not found etc. This means that exceptions could be thrown by checking values.
For the reader of your code - again my personal opinion - it is much easier to follow the flow if you can be certain that it is not put aside by all kinds of strange throws (which is essentially gotos in disguise if used as part of the program flow). You simply have less to think about.
This is in my opinion a good thing. "Smart" code is hard to wrap your head around.
On a side note - JVM's get much much smarter - coding for efficiency usually doesn't pay off.
Normally, one would assume that try-catch is more expensive because it looks heavier in the code, but that entirely depends on the JIT. My guess is that it's impossible to tell without having a real case and some performance measurements. The comparisons could be more expensive, especially when you have many values, for example, or because you have to call equals() since == won't work in many cases.
As for which one you should chose (as in "code style"), my answer is: Make sure that the user gets a useful error message when it fails. Anything else is a matter of taste and I can't give you rules for that.
To be safe, assume exceptions are expensive. They often are, and if they aren't it will at least push you towards using exceptions wisely. (Entering a try block is usually trivially cheap, since implementors do their best to make it so, even at the cost of making exceptions more expensive. After all, if exceptions are used properly, the code will enter the try block many times more often than it will throw.)
More importantly, exceptions are a style issue. Exceptions for exceptional conditions make code simpler because there's less error-checking code, so the actual functionality is clearer and more compact.
However, if exceptions might be thrown in more normal circumstances, there's invisible flows of control that the reader has to keep in mind, comparable to Intercal's COME FROM...UNLESS... statement. (Intercal was one of the very early joke languages.) This is very confusing, and can easily lead to misreading and misunderstanding the code.
My advice, which applies to every language and environment I know about:
Don't worry about efficiency here. There are strong reasons besides efficiency for using exceptions in a way that will prove efficient.
Use try blocks freely.
Use exceptions for exceptional conditions. If an exception is likely, test for it and handle it in another way.
a question like this is like asking,
"is it more efficient to write an interface or a base class with all abstract functions"
does it matter which is more efficient? only one of them is the right way for a given situation
Note that if your code doesn't throw exceptions then it doesn't always imply that the input is within bounds. Relying on throwing exceptions by the standard Java (API + JVM), such as NullPointerException or ArrayIndexOutOfBoundsExceptions is a very unhealthy way to validate input. Garbage-in sometimes generates garbage-but-no-exception-out.
And yes, exceptions are quite expensive. They should not be thrown during a normal processing flow.
Optimizationally, I think you're going to find it's probably a wash. They'll both perform alright, I don't think exception throwing is ever going to be your bottleneck. You should probably be more concerned with what Java is designed to do (and what other Java programmers will expect) and that is thrown exceptions. Java is very much designed around throwing/catching exceptions and you can bet the designers made that process as efficient as possible.
I think it's mostly a philosophy and language culture sort of thing. In Java, the general accepted practice is that the method signature is a contract between your method and the code calling it. So if you receive an improper value, you generally throw an unchecked exception and let it be dealt with at a higher level:
public void setAge(int age)
{
if(age < 0)
{
throw new IllegalArgumentException("Array can't be negative");
}
this.age = age;
}
In this case, the caller broke their end of the contract, so you spit their input back at them with an exception. The "throws" clause is for use when you can't fulfill your end of the contract for some reason.
public void readFile(String filename) throws IOException
{
File myfile = new File(filename);
FileInputStream fis = new FileInputStream(myfile);
//do stuff
fis.read();
//do more stuff
}
In this case, as the method writer, you've broken your end of the contract because the user gave you valid input, but you couldn't complete their request due to an IOException.
Hope that kinda puts you on the right track. Good luck!

Throwing exceptions in Java

I have a question about throwing exceptions in Java, a kind of misunderstanding from my side, as it seems, which I would like to clarify for myself.
I have been reading that the two basic ways of handling exception code are:
1.) throwing an exception in a try-block with "throw new ...", and catching it immediately in a catch-block - the so called try-throw-catch mechanism.
2.) throwing an exception in a method with "throw new ..." and then declaring in the header of the method that this method might throw an exception with "throws ..." - the so called pass-the-buck.
I have recently read that "it doesn't make any sense to throw an exception and then catch it in the same method", which made me think whether I understand the thing in the wrong way, or the person who had written this had something else in mind. Doesn't the first way of handling exceptions does exactly this (the try-throw-catch mechanism) ? I mean, it throws an exception and catches it in the same method. I have read that it is a better practice to throw an exception in one method, and catch it in another method, but this is just one (probably better) way. The other way is also legal and correct, isn't it?
Would you, please, give me a comment on this ? Thank you very much.
Exceptions should be thrown from a method when that method is incapable of resolving the exception on its own.
For example, a FileNotFoundException is thrown from new FileInputStream(new File(filename)) because the FileInputStream itself can't handle a case where a file is missing; that exception needs to get thrown so the end-user application can handle the problem.
There are some cases where exceptions could be handled within a method. For example, a Document model method throwing a BadLocationException could be handled within a sufficiently intelligent method. Depending on the problem, either the exception can be handled or re-thrown.
(Anyway, I'd argue that throwing an exception from within a try-catch block so the catch block can be executed represents really bad logic flow)
I think you misunderstood the first case. Normally you add a try-catch-block when you call some method which may throw exceptions. Catching locally thrown exceptions indeed doesn't make much sense. In particular you shouldn't use exceptions to exit from loops, as this is extremely slow compared to a standard approach.
Doesn't the first way of handling
exceptions does exactly this (the
try-throw-catch mechanism)? I mean, it
throws an exception and catches it in
the same method.
That's not a "way of handling exceptions" - it's utter nonsense. The whole point of exceptions is to let another method up the call stack handle it. If you're going to handle the condition within the same method, there's no point in using an exception - that's what if() is for! If that makes the control flow of your method too complicated, you should probably refactor some of the logic into separate methods - and then it might make sense to have those throw exception that the remaining method body catches.
That being said, I can imagine one special case where it could make sense to throw and catch an exception in the same method: when you're already calling a method that may throw an exception and have a catch block to handle it, then in some cases it could make sense to throw an exception to indicate a similar problem that the existing catch block can handle in the same way.
The person who wrote "it doesn't make any sense to throw an exception and then catch it in the same method" is entitled to their opinion, but it's not widely shared. There are plenty of cases where throwing and catching an exception in the same method is what's needed. The simplest is where you are doing a sequence of operations and the failure of any one of them makes the rest invalid. If you detect that one of these operations fails it's perfectly reasonable to throw an exception and catch it at the end of the method. In fact it's the logical way of doing things. Arguably you could rewrite the code to not use the exception, maybe with some status flags and a break statement or two, but why would you? Using an exception makes it clear what's going on and improves code readability.
I'm gonna answer your questions in turn, then add some comments to the end. I'm not an authority on exception handling, but I hope my comments are helpful.
"Doesn't the first way of handling exceptions does exactly this"?
My answer is yes, as you describe it the first method does operate by throwing and catching an exception in the same method. However, I don't know that try-throw-catch has to work as you describe it.
"I have read that it is a better practice to throw an exception in one method, and catch it in another method, but this is just one (probably better) way. The other way is also legal and correct, isn't it?"
I agree that catching exceptions from a second method is better, but the first way is legal. Is it correct? well that's for you to decide, it is your code, after all.
For the most part, I agree that it doesn't make sense to throw an exception then immediately catch that exception in the same method. If we do this because the method is particularly long/complex and handling the error using other logic would complicate things more, then I would suggest moving some of this logic to another method and calling that method and catching its exception.
If our code is simpler, then it may be easy to handle the error using code that doesn't consist of throwing an exception.
My comments:
The try-throw-catch mechanism you mentioned may not need the exception to be thrown in the same method. I would have to read the text you found to be certain, but I would expect that it isn't necessary. If it didn't need the exception to be thrown in the same method, then your exceptions handling strategy is a combination of 1) and 2).
In the combo, one method would use try-throw-catch mechanism to catch an exception thrown by a called method. It seems to me that 1) and 2) should work together to form your exception handling strategy.
Now, maybe someone will come along and give us some wonderful reasons why we might want to throw an exception in the same method. I expect there are some, but to me they seem the exceptions, not the rule.
Cheers,
Ed
With the first way do you mean something like this:
try {
ok = doSomething();
if (!ok) {
throw new Exception("Error");
}
ok = doSomethingElse();
}catch (Exception e) {
}
This will allow you to exit the try-catch block without executing the rest of it. This is the only valid usage I can think of throwing an exception with throw and catching it yourself in a try-catch block. However, standard if blocks should be used instead. I don't understand why someone should throw an exception and then catch it himself.
The second way is more standard, especially if the caller of the method that throws an exception is an external module. This is a way of signaling that something real wrong happened. It is the responsibility of the caller to handle the exception.
If you're going to manually throw an exception, then obviously you know there has been some error that needs to be handled. Rather than throw the new exception, then catch it, then immediately handle the error, why not just handle the error? You (and the processor) don't need to go through all the work of generating an exception and catching it. The exception also makes the code harder to read and debug.
You would throw an exception, rather than just handling the error immediately, if:
Other code, like the code that called your method, should handle the error. For example, if your code is not UI code, then it probably shouldn't generate windows. This is your method #2.
You can take advantage of the try, catch, finally block. It's possible that you could write cleaner code this way, but I think that 90% of the time your code would be more readable using simple if statements.
My expierence is that using the first method gets your code quickly unreadable - since the functionality and the error-handling is getting mixed up. BUT it makes sense in some cases where you have a try{}catch{}finaly{} - for example in file handling or database handling where you ALLWAYS want the connection to be closed.
try{ //do something
}catch(Exception ex){
//log
}finally{
//connection.close
}
For everything else I use the second option - just for the reason to centralize my error-handling routines and keep the readability of the code implementing the businesslogic itself.
In my opinion, try blocks that you write should not include any "throw new" that are caught inside the same method. When you throw an exception, you're saying "I've encountered a situation that I can't handle; somebody else will have to deal with it." Your method with the "throw new" should either create an unchecked exception to throw or declare a checked exception in its method signature.
If you're using 3rd party classes that may throw exceptions, your method should have a try/catch block if you can actually handle the situation if an exception arises. Otherwise, you should defer to another class that can.
I don't create my own exception and then catch it in the same method.
Using an exception for control flow is specifically dealt with in Effective Java, 2nd Edition by Joshua Bloch, Item 57:
Item 57: Use exceptions only for exceptional conditions
...exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow. [italics mine]
So while it certainly "works" to use exceptions to control flow, it is not recommended.
The reason why that would seem as nonsense ( throwing and catching in the same method ) is because that would be an scenario of using exceptions for flow control. If you already have enough data as to identify the condition where the exception should be thrown then you could use that information to use a condition instead.
See below:
1) Throwing and catching exception in same method ( wrong )
public void method() {
try {
workA...
workA...
workA...
workA...
if( conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) {
throw new IllegalStateException("No the rigth time" );
}
workB...
workB...
workB...
workB...
} catch( IllegalStateException iee ) {
System.out.println( "Skiped workB...");
}
workC....
workC....
workC....
workC....
}
In this scenario the exception throwing are used to skip the section "workB".
This would be better done like this:
2) Using condition to control flow ( right )
public void method() {
workA...
workA...
workA...
workA...
if( !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) ) {
//throw new IllegalStateException("No the rigth time" );
workB...
workB...
workB...
workB...
}
workC....
workC....
workC....
workC....
}
And then you can refactor the condition:
if( !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) ) {
for
if( canProceedWithWorkB() ) {
implemented as:
boolean canProceedWithWorkB() {
return !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() );
}

Throwing exceptions to control flow - code smell? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Consider this code (Java, specifically):
public int doSomething()
{
doA();
try {
doB();
} catch (MyException e) {
return ERROR;
}
doC();
return SUCCESS;
}
Where doB() is defined as:
private void doB() throws MyException
Basically, MyException exists only in case doB() meets some condition (which is not catastrophic, but does need to somehow raise this condition) so that doSomething() will know to exit with an error.
Do you find the use of an exception, in this case to control flow, acceptable? Or is this a code smell? If so, how would you refactor this?
Is it really important for doC() to be executed when doB() fails? If not, why not simply let the Exception propagate up the stack to where it can be handled effectively. Personally, I consider using error codes a code smell.
Edit: In your comment, you have described exactly the scenarion where you should simply declare
public void doSomething() throws MyException
It entirely depends on what that error condition is, and what the method's job is. If returning ERROR is a valid way of handling that error for the calling function, why would it be bad?
Often, however, it is a smell. Consider this:
bool isDouble(string someString) {
try {
double d = Convert.ParseInt32(someString);
} catch(FormatException e) {
return false;
}
return true;
}
That is a very big code smell, because you don't expect a double value. You just want to know whether a string contains a double.
Sometimes, the framework you use doesn't have other ways of doing what you want. For the above, there is a better way:
bool isDouble(string someString) {
bool success;
Convert.TryParseInt32(someString, ref success);
return success;
}
Those kinds of exceptions have a special name, coined by someone whose blog I read recently, but sadly, I forgot its name. Please comment if you know it. Last but not least, the above is pseudocode. I'm not a C# developer so the above doesn't compile, I'm sure, but TryParseInt32 / ParseInt32 demonstrates that well I think, so I'm going with C#.
Now, to your code. Let's inspect two functions. One smells, and the other doesn't:
1. Smell
public int setupSystem() {
doA();
try { doB(); }
catch (MyException e)
{ return ERROR; }
doC();
return SUCCESS;
}
That's a code smell, because when you want to setup a system, you don't want it to fail. Failing to setup a system means you can't continue without handling that error.
2. OK
public int pingWorkstation() {
doA();
try { doB(); }
catch (MyException e)
{ return ERROR; }
doC();
return SUCCESS;
}
That is OK, because the purpose of that method is to test whether the workstation is still reachable. If it's not, then that is part of the result of that method, and not an exceptional case that needs an alternative return path.
My only problem with the OP's code is that you're mixing paradigms -- doB shows an error by throwing an exception, while doSomething shows an error by returning a code. Ideally, you would pick one or the other. Of course, in legacy maintenance, you might not have that luxury.
If you pick returning error codes, that's OK, but I dislike it because it encourages you to use side channels (like global variables) to communicate state on failure, rather than bundling that state into an exception and letting it bubble up the stack until you can do something about it.
I've never liked using exceptions for control flow (in some languages, like the CLR, they're expensive).
If you can modify doB(), the best thing to do is change it to return a boolean that indicates success or failure, so your example would look like:
public int doSomething()
{
doA();
if (!doB()) {
return ERROR;
}
doC();
return SUCCESS;
}
Exceptions should be used when:
a function cannot complete normally, and
when there is no return value that can be used to indicate the failure, or
when the thrown exception communicates more information than return FAILURE; can, for instance, nested exceptions or the like.
Remember above all that exceptions, like return values or method parameters, are simply messages sent between different parts of the code. Strive to optimize the balance between the information communicated via these methods, and the simplicity of the API. When a simple SUCCESS/FAILURE flag is all that's needed (and the method doesn't need to return other values), use that. If the method already must return a value, you usually need to use an exception (which is, to one way of looking at it, simply an "exceptional" return value from the method). If the failure information that must be communicated is too rich to be communicated in a return value (for instance, the reason for an I/O failure), use an exception.
Finally, error handling is a design decision, and there is no one-size-fits-all set of rules that will cover all cases.
Using exceptions to control flow, is definitely bad. Exceptions should be thrown only in exceptional conditions.
However, having a utility method that simply either throws an exception or does nothing is not particularly bad. For example, you may wish to validate all the arguments on entry to a method, or check that internal state is still valid between complex calculations (that for some reason you cannot force internally, perhaps you're accepting closures and executing them). In these cases it would not be a bad idea to extract the consistency checking into its own method, to improve the readability of the "actual" method implementation.
The dividing line is really that you should throw an exception when something outside of normal operating parameters is encountered, and things are so bad that there's no real way for the method to proceed with what it does.
As an example of what not to do, this would be using exceptions for flow control:
public int calculateArraySize(Object[] array)
{
int i = 0;
try
{
array[i++];
}
catch (ArrayIndexOutOfBoundsException ignore) {}
return i;
}
I believe it will return the right result, but it will be horribly slow and inefficient, as well as difficult to read for people who are used to exceptions being used properly. ;-)
On the other hand, something like this would be OK in my opinion:
public void myMethod(int count, Foobar foo) throws MyPackageException
{
validateArgs(count, foo);
// Stuff
}
private void validateArgs(int count, Foobar foo) throws MyPackageException
{
if (m_isClosed)
{
throw new IllegalStateException("Cannot call methods on a closed widget");
}
if (count < 0)
{
throw new IllegalArgumentException("count must be greater than zero");
}
foo.normalise(); // throws MyPackageException if foo is not fully initialised at this point
}
Despite the fact that all the second method does is potentially throw an exception, it's not doing this to control the program flow but is raising them in response to exceptional conditions.
It's ok to throw Exception in case of error, as in doB().
But problem is function doSomething().
You shouldn't use return statements to indicete success or failure. You should do:
try {
doB();
} catch (MyException e) {
throw MyException2(e);
}
Exceptions should not be used just to control flow. Checked exceptions should be used to tell calling code that certain conditions of the API contract were not met. I would not design doSomething to handle cases where calls to doB would fail often by using a try/catch block. If frequent failure was a case that you needed to deal with, I would design doB to return a success or failure boolean to indicate to its calling methods whether to continue on to their own doC-type methods:
public int doSomething() {
doA();
if ( doB() )
doC();
return SUCCESS;
} else {
return ERROR;
}
}
Depending on doB's logic, you could have some return values pointing if it was ok or not, and then doSomething could use the returned value to handle the situation in an appropriate way.
Exceptions are for non-standard behaviour. So yes it is ok to use them for controlling flow.
As Sun puts it:
Generally speaking, do not throw a RuntimeException or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.
Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.
Just remember to not subclass RuntimeException but Exception as those are faster.
I think it is very bad use of exceptions, plain and simple. I would create normal functions that return normal values and leave exceptions to what they are designed for.
As others have indicated, it really depends on the intended functionality of the methods involved here. If doSomething()'s role is to check something, returning a code that allows normal execution of its calling methods to continue (albeit on different paths depending on the code returned) then having it return that int may be fine. In that case, though, doB() should probably be consistent and return a boolean or something that doSomething() can check instead of throwing an exception which won't really do anything else.
If doB() were a public method of a another class that might have other uses outside of doSomething() (as opposed to a private method in the same class as you indicated) and it throws an exception and you want to use it in doSomething() (which has the same role indicated above), then your example would be fine.
The fact that the code you return when doB() throws an exception is called ERROR, though, indicates that it's probably a failure that would prevent whatever operation doSomething() is a part of from completing. In that case, you should probably not catch the exception thrown by doB() and just let it be thrown up the stack until it reaches a point where it can be handled or until it reaches your general error handler which can report/log it or whatever.
In C#, throwing exceptions is relatively expensive, performance-wise – thus another reason to avoid their use for flow control. Is that the case in Java? Yes, there's an argument to be made for not over-analyzing performance ahead of time. But if you know something will take extra time, and its easy to avoid, shouldn't you do it? Unless you truly don't care!
See the top answer to this question:
How slow are Java exceptions?
It turns out they're at least 50 times slower than normal code flow. So I'd say that using exceptions in the usual run of code is definitely a bad idea.
Here is how I would handle it:
public void doSomething()
throws MyException{
doA();
try {
doB();
} finally {
doC();
}
}
If an error occurs in doB(), the exception will propagate up the stack.
You guys are killing me here. You NEVER want to use exceptions to control flow. It wouldn't be much different than using goto statments everywhere!
Exceptions are exception, meaning something un expected has happened. Something so much so we are halting the execution of the application. Anyone who has worked on an application were this type of exception flow control is baked in will want to hunt down the developer who did this and throttle him (or her).
Using exception as flow control makes maintainence and new feature development a nightmare!

Categories