Unexceptional exceptions - java

Is this a thing?
I want to throw my own exceptions just to make it easier to handle.
They're unexceptional though because it is likely to happen, not an exceptional case. Such as if the user selects a wrong file type from a browser. Yes I could handle it but it would be far easier if I threw an exception especially for sub methods, since I would need to somehow tell the parent method that the sub method failed so do something differently. This I think is easier with throwing exceptions.
So is it okay to throw an exception in normal situations?

I would have to say answers to this question are to some extent opinion-based, but the general consensus seems to be that it's a bad idea to abuse exceptions for regular flow control.
It's a well-documented anti-pattern, and the primary reasons for it to be considered as such are that:
it obscures your real exceptions,
leads to GOTO-like spaghetti code, and
violates the principle of least astonishment.

The typical use case is:
Present some data to the user
Accept a selection (or a cancellation)
Check the selection (e.g., correct file type)
If correct, return the selection
If not correct, provide an error message (still in the context of this dialog) with the choices "retry" and "abort"
On abort, return a "null value"
On retry, go back to 2.
There is really no need for an exception to handle incorrect entries or even the cancellation (after 2 or 6). Some other exception might be thrown if your program runs into an IOException while accessing the file system or similar.
The only burden the caller should have is to check for a "null value" (null or whatever is suitable) being returned to indicate user's choice of not wanting to do something - an option that should typically be provided.

Related

Should I ever use exceptions in java if I can solve problem without them?

Are exceptions like goto in c don't use it if you don't have to or is it OK to use them as much you want to, and why?
Are they hard on CPU, memory or something else?
You should regard exceptions as a tool that can help you make good software design, similar to data encapsulation (private fields with Getters/Setters), inheritance, interfaces, etc.
The idea of the exception concept in Java is to give you a good way of moving error handling to a spot in your code where it makes most sense. When you face a problem at some line of code, then the first thing you should ask yourself is: Should this method/class that I have here be responsible for handling the problem, or is there a better, more high-level place in my software that should handle it? If you find the latter to be the case, then throwing an exception to that higher-level instance is good design.
Think of it as this: Let's say someone at your work place gives you a pack of bills and tells you to add up the total billing amount. And then in the middle of the bills you find another document that is something completely different. In that case, it would make more sense to go to the person who gave you the pack of documents and let them handle it, instead of deciding for yourself what to do with it, because you may not know what exactly to do.
Example in software: Let's say you have a method that expects a birth date and should calculate the age of the person (difference to current date). But then you find that the given date is incorrect, for instance because it is in future. This method should not deal with fixing the problem, because you might not know how. Is this program a console program and you should print an error, or will it have a GUI? So, you throw an exception to a higher level of the application that knows if there is a GUI or not, and thus whether to print an error to console or show a dialog in the GUI. That's just a simple example, but I hope you get what I mean.
To sum up: Exceptions are nothing "bad" in Java. When used properly, they are a good thing that help you avoid putting responsibilities into objects that they shouldn't have.
...don't use it if you don't have to or is it OK to use them as much you want to...
According to Joshua Bloch's Effective Java:
Exceptions are, as their name implies, to be used only for exceptional
conditions; they should never be used for ordinary control flow.
In order to fully understand this, let's take a look on Java exception. In Java we can find three types of exceptions: checked exceptions, runtime exceptions, and
errors.
Checked exceptions: as their name implies, they should be checked/treated by the developer. Moreover, the compiler forces you to handle this exceptions by try...catch or propagating them upwards by marking the method with throws keyword. These kind of exceptions usually extend the builtin `Exception' class.
Unchecked exceptions: in this group enter both runtime exceptions and errors. The difference between checked exception and unchecked exceptions is that the compiler does not forces you to handle unchecked exceptions. Since they should be used to indicate programming errors, usually it is a good idea to not catch them at all and focus on preventing them. Errors are reserved for use by the JVM to indicate critical failures which usually prevent your program to be recoverable. All of the unchecked
exceptions should subclass RuntimeException class.
So, to give you a response to your first question, it is OK to use exceptions as long as it makes your code readable, more understandable. Moreover, you should be able to deal with exceptions, since compiler will force you to do so. This does not mean that you should throw exceptions whenever you want.
Now let's talk about performance. To repeat myself, exceptions should be used in exceptional cases. This means that they are not as performant as a single if..else would be. Using them wisely, you wont really notice a performance hit, overusing them can cause problems. Exceptions should never be used for control flow (gotos can be used for). In case of memory, every exception creates a new object, which should contain some information about the exception itself. Creating many exceptions would result in occupying more memory, but I don't think that this can be a problem nowadays.
Should I ever use exceptions in java if I can solve problem without
them?
It depends, and is up to you on deciding against or in favor of them. Usually, exceptions are thrown to notify the lack of something (example: no money to withdraw from a credit card, non-existent file to open, etc.) In order to avoid using exceptions in these cases, it is a good idea to return on Optional of something.
This answer is based on Joshua Bloch's Effective Java book. For more information I suggest reading the Exceptions chapter.

How to find a list of possible Java Exceptions

Lets say your program is going to do a variety of math computations and want to know the available exceptions that are possible to capture to see if any are applicable.
Or, the program will be doing a lot of file i/o and other things and you want to capture specific exceptions instead of simply capturing Exception.
Maybe you may want to know if one application is even applicable in the scenario being coded.
What is the recommended way to go about researching what exceptions are available to be captured when generating code to do specific activity?
Using a IDE like Intellij or Eclipse will let you know most of the exceptions that the library code you are using throws, depending on it's javadoc(Like FileNotFoundException) and majority of the times, these are the exceptions that you should worry about.
Other exceptions like divide by zero, null pointer exception will certainly depend on the code you are writing. For example if you getting an object from a different class, you might want to check if it is null before doing any operations on it. Similarly if you are dividing by something, like K/X , you should have an idea whether X is ever going to be 0 or not.
The recomended way is to look into the javadoc of that method.
Hopefully the software author of that code wrote the javadoc in the recomended way, to also list the Runtime Exceptions that a method throws.
You can usually find this information in the Docs for the method you want to use. It will tell you what exceptions it can throw in what cases. There is no general purpose "find all exceptions" technique. This is probably a good things, because if you don't know how or why an exception is created, you probably don't know enough to handle it.
You can trace through the source of the code you are calling to find all the specific exceptions. The problem with this is that the time this takes esp since it could change between different versions of software is very high.
In general you can trust the Javadoc for broad checked exceptions, but this usually won't tell you about all specific exception or all RuntimeExceptions. (Including all future exceptions)
Note: you may wish to take different actions based on the message as well as the type of exception.
For this reason I suggest you focus on the specific exceptions which you handle differently, and have a catch all IOException or similar for unexpected exception which by their nature mean you can't know how to handle them.
There are two types of exceptions, checked and unchecked. If you don't handle checked exception you will get a build failure. You can identify checked exception if you are using any IDE. But unchecked exception are bit tricky and you may need to refer the API documentation to understand what they are, because unless it's thrown you may not know that exception can occur. Again some IDEs give you hints based on your code, for example class casting, null checking.

Java proper use of exceptions and cost

I'm trying to take a slightly stricter approach to coding this class. Instead of my usual cowboy coding style, creating as I go, I'd like to first lay out the methods, the variables, the comments... all that jazz.
So now here is the concept of the exception.
Should I think "What are all the things that could possibly go wrong in this function?" and throw an exception for each (if existing ones aren't descriptive enough then create a new one)? It seems this is the most precise option.
Should the line of thinking be "These are things that will probably go wrong, I'll throw a general exception for everything else."
How about "Nothing will probably go wrong, I don't need to throw an exception, worse case I can throw a runtime exception in the off chance something does go wrong..."
What I'm worried about here is the performance of the error handing. Ideally I could imagine Java just converting those exceptions into nice little if statements or some sort of jump statement. I imagine this could only cost one operation or so.
I can also imagine Java creating a circus 20 calls deep for the sake of abstraction, maybe then they are costly and I should pretend I'm coding in C all over again?
I wrote the question in a silly way since its more fun for both of us that way, but its a serious question. I'm sure there is some balance, maybe a rule of thumb or ten. How do you think about exceptions?
Edit: I'm not suggesting I use exceptions for processing. What I am talking about is the number and preciseness of the exceptions (How specific an error, perhaps?).
Exceptions ARE more expensive at run time, so should not be used as a part of "normal" processing.
Exceptions are for exceptional circumstances. Anticipated failures should not generate an exception. For example a user providing invalid input (wrong password, invalid zip code, etc.) should not generate an exception.
Exceptions are for bugs, and serious unrecoverable system failures.
Note that JDBC's use of exceptions is poorly designed (according to the principles I'm suggesting).

What is the purpose of wrapping a lower level exception in Java if I'm just going to throw my wrapper exception?

I understand throwing exceptions specific to the application layer you're in, but what is the purpose of all of this exception handling overhead if you're:
Just going to let the exceptions bubble up to the top.
Never going to do anything "unique" with the wrapped exception.
For example, I have a DAO that throws a SQLException, and the next layer up is a manager that calls the DAO. The commonly accepted paradigm is that I create a manager exception, wrap my SQLException, and then throw the manager exception. Why? If another class up the chain is going to deal with it anyhow, then why wrap it?
In your example, it might not be useful. But suppose you're writing an interface with many possible implementations. Suppose for example that two years from now, you switch from a SQL database to a NoSQL one. Your DAO will then be forced to declare NoSQLException, and all the calling code will have to be rewritten. Whereas if the SQLException or NoSQLException is wrapped inside your custom exception, the calling code can stay as it is.
In your specific example, if you have a service layer that calls the DAO, you don't want clients to see SQL Exceptions such as "ORA-00118: unique constraint (BLABLA) violated".
Making such exception messages meaningful to upper level layers is one reason why you might consider wrapping them into more meaningful exceptions.
Catching and re-throwing is not handling anything. Better to let it bubble up in that case.
Catching a checked exception and re-throwing as unchecked can be a useful thing to do, but it's better to add more specific information.
You should only wrap and throw an exception if you're going to add some useful info to it, or to make it specific to your domain. Otherwise you should just be letting an exception bubble up to where it can be handled. I'm guessing that you're looking at some suspect code for your examples.
One example for wrapping exceptions, that might actually be useful, is to "convert" implementation-specific exceptions to something more specific to a framework in an IoC/DI scenario. For example, if you have a framework that does some work, you want to shield the client code from having to "know" a bunch of specific exceptions. So you create a set of common exceptions that your plug-ins throw and that your client code knows and can handle. Like data access exceptions for a bunch of different back ends.
java enforces you to explicitly declare which exceptions can be thrown. wrapping exceptions prevent:
1. expose what is your specific implementation (the higher level might not know that you are using sql as your data base, so you can just throw MyAppException).
2. otherwise, the list of declared exceptions would increase overtime, which will enforce the higher level to take care of all of them, which might be not very neat.
I think it all depends on how specific you want to be and if you want to include more information in your custom exception. Otherwise, you can just allow exceptions thrown by other methods to bubble up and handle them however you see fit.
In your case, SQLException might be too generic, so wrapping it in your own custom exception can help more easily determine where it was thrown in your application and to include more specific information.
So different implementations of the DAO using different datastores can transform the different storage-specific exceptions to the same abstracted storage exception. Then they just include the original for debugging purposes.
I would suggest that in many cases, exceptions could be most usefully handled by reducing them to three types:
OperationFailedStateOkException
The operation could not be completed, but the local and global system state is okay except to the extent implied by that failure (e.g. trying to reference a non-existent item in a Dictionary).
OperationFailedLocalStateCorruptException
The operation could not be completed, and the local system state is corrupt (e.g. trying to reference an item from a corrupted Dictionary).
OperationFailedGlobalStateCorruptException
The operation could not be completed, and the global system state is corrupt (e.g. a shared cache got corrupted).
Note that in many cases the caller of a routine won't be nearly as interested in why it failed as in what the failure implies about the state of the system. Exceptions of the first type may generally be safely caught, and execution resumed, if the programmer knows why they might occur and what to do about them. In some cases, they may need to be rethrown as exceptions of the second type (e.g. if the system was unable to perform some operation which would be necessary to maintain consistency in a data structure). Those of the second type should only be caught and rethrown as the first type at a level where the corrupt state is going to be abandoned (e.g. a "Load document" routine might catch such exceptions and rethrow as a "state ok" exception if any corrupt data structures used in the failed attempt to load a document are going to be jettisoned). Those of the third type should generally trigger a program shut down.
To be sure, it may be useful to have some gradations between the different types (e.g. indicating a global problem sufficient that the program should be shut down gently, saving user data, versus indicating that things are so bad that attempting to save user data would corrupt things worse). Nonetheless, catching exceptions and rethrowing one that indicates something about the system state may be nicer than simply leaving higher levels of the code to wonder what to do with an InvalidArgumentException.

Is using checked exceptions in external APIs a good idea?

Seeing a checked expection in API is not rare, one of the most well known examples is IOException in Closeable.close(). And often dealing with this exception really annoys me. Even more annoying example was in one of our projects. It consists from several components and each component declares specific checked exception. The problem (in my opinion) is that at design time it was not exactly known what certain exceptions would be. Thus, for instance, component Configurator declared ConfiguratorExeption. When I asked why not just use unchecked exceptions, I was told that we want our app to be robust and not to blow in runtime. But it seams to be a weak argument because:
Most of those exceptions effectively make app unusable. Yes, it doesn't blow up, but it cannot make anything exepting flooding log with messages.
Those exceptions are not specific and virtually mean that 'something bad happened'. How client is supposed to recover?
In fact all recovering consists from logging exception and then swallowing it. This is performed in large try-catch statement.
I think, that this is a recurring pattern. But still checked exceptions are widely used in APIs. What is the reason for this? Are there certain types of APIs that are more appropriate for checked exceptions?
There have been a lot of controversy around this issue.
Take a look at this classic article about that subject http://www.mindview.net/Etc/Discussions/CheckedExceptions
I personally tend to favor the use of Runtime exceptions myself and have started to consider the use of checked exceptions a bad idea in your API.
In fact some very popular Java API's have started to do the same, for instance, Hibernate dropped its use of checked exceptions for Runtime from version 3, the Spring Framework also favor the use of Runtime over checked exceptions.
One of the problems with large libraries is that they do not document all the exceptions that may be thrown, so your code may bomb at any time if an undocumented RuntimeException just happens to be thrown from deep down code you do not "own".
By explicitly declaring all those, at least the developer using said library have the compiler help dealing with them correctly.
There is nothing like doing forensic analysis at 3 in the morning to discover that some situation triggered such an undeclared exception.
Checked Exceptions should only be thrown for things that are 1) Exceptional they are an exception to the rule of success, most poor exception throwing is the terrible habit of defensive coding and 2) Actionable by the client. If something happens that the client of the API can't possibly affect in any way make it a RuntimeException.
There's different views on the matter, but I tend to view things as follows:
a checked exception represents an event which one could reasonably expect to occur under some predictable, exceptional circumstances that are still "within the normal operating conditions of a program/typical caller", and which can typically be dealt with not too far up the call stack;
an unchecked exception represents a condition that we "wouldn't really expect to occur" within the normal running environment of a program, and which can be dealt with fairly high up the call stack (or indeed possibly cause us to shut down the application in the case of a simpler app);
en error represents a condition which, if it occurs, we would generally expect to result in us shutting down the application.
For example, it's quite within the realms of a typical environment that under some exceptional-- but fairly predictable-- conditions, closing a file could cause an I/O error (flushing a buffer to a file on closing when the disk is full). So the decision to let Closable throw a checked IOException is probably reasonable.
On the other hand, there are some examples within the standard Java APIs where the decision is less defensible. I would say that the XML APIs are typically overfussy when it comes to checked exceptions (why is not finding an XML parser something you really expect to happen and deal with in a typical application...?), as is the reflection API (you generally really expect class definitions to be found and not to be able to plough on regardless if they're not...). But many decisions are arguable.
In general, I would agree that exceptions of the "configuration exception" type should probably be unchecked.
Remember if you are calling a method which declares a checked exception but you "really really don't expect it to be thrown and really wouldn't know what to do if it were thrown", then you can programmatically "shrug your shoulders" and re-cast it to a RuntimeException or Error...
You can, in fact, use Exception tunneling so that a generic exception (such as your ConfiguratorException) can give more detail about what went wrong (such as a FileNotFound).
In general I would caution against this however, as this is likely to be a leaky abstraction (no one should care whether your configurator is trying to pull its data from the filesystem, database, across a network or whatever)
If you are using checked exceptions then at least you'll know where and why your abstractions are leaky. IMHO, this is a good thing.

Categories