Reputation: 655
I've seen some code recently where the author was throwing exceptions for almost every constructor and throwing runtime exceptions for things like the code below, in a method that returns int:
if(condition){
return 1;
}
if(condition){
return 2;
}
if(condition){
return 3;
}
throw new RuntimeException("Unreachable code");
// method ends here
I wouldn't have personally thrown an exception there, because I would have structured it using if and else if statements, and in this particular case your code would be fundamentally wrong for it not to satisfy one of the conditions anyway.
There are plenty of places you could throw runtime exceptions, that would never be reached if you're code is working correctly, sometimes it just seems like the author doesn't trust the code to work, in the case of the code block above. Also, every constructor could throw an exception for if it doesn't initialize correctly, but you could also structure it so that the object would be null - which you could then check for in main, for instance.
What I'm asking, basically, is when is it worth throwing an exception?
Upvotes: 4
Views: 2303
Reputation: 81
GhostCat has basically covered all that need to be said when and why we should use exceptions. Just to take it further, the best thing to do is to weigh the cost benefit of including an exception. The cost in this context refers to performance as well as degraded client friendliness of the application while the benefit is the smooth running of the application as well as being user-friendly. In my opinion first one should distinguish between application and system error. Then these errors further need to be scrutinised after dichotomizing them into compile and runtime ( note that compile time errors normally do not need to be handled with exception but to debug and find out issues you need to handle them using debug tools such as assert of C++). Even if the nitty-gritty of inclusion of exception handlers depends on the context of the specific application, generally, one can postulate the following principles as a starting point:
1- Identify critical hotspot crash points of the code;
2- Distinguish between system and application errors;
3-Identify run time and compile time errors;
4- Handle compile time error using debugging tools such as assert or preprocessor directives. Also, include exception handlers or trace or debug to handle runtime errors 4-weigh the consequences of handling exceptions at run time;
5- Then provide a testable framework, which normally can be handled during Unit Test, to identify where exceptions need to be included or not.
6- Finally, decide where you need to include the exception handlers for your production code taking into account factors you think are decisive and need to include exception handler to handle them.
7- Finally finally .... you need to have a crash proof exception handler that should be triggered in the unlikely scenario that the application crashes and include fallback safety to handle states to make the application very user-friendly.
Upvotes: -1
Reputation: 140613
The point of exceptions is to communicate exceptional situations.
In that sense: if it is absolutely unexpected that all your conditions are false in your example, and that there is also no valid return value to indicate that situation, then throwing that RuntimeException is the reasonable thing to do here; but I would probably change the message to:
throw new RuntimeException("All conditions failed: " + some data)
As said: it is about communicating; in this case to the person debugging the problem. So it might be helpful here to include the information that is required to understand why exactly all those checks turned out false
.
The point is: there is a contract for that method; and that contract should include such details. Meaning: if that method is public, you should probably add a @throws RuntimeException with a clear description.
And it is also a valid practice to use RuntimeException for such situations; as you do not want to pollute your method signatures with checked exceptions all over the place.
Edit: of course, balancing is required. Example: my classes often look like:
public class Whatever {
private final Foo theFoo;
public Whatever(Foo theFoo) {
Objects.requireNonNull(theFoo, "theFoo must not be null");
this.theFoo = theFoo;
So, there might be a NPE thrown from my constructors; yes. But: only there. All my methods can rely on the fact that all fields were initialized to non-null; and they are final, so they will always be non-null.
Meaning: one has to stay reasonable; and "develop" a feeling for: which problems are exceptional but possible; and which ones are so impossible that you don't pollute your code all over the place to check for them.
Finally; just to make that clear - adding exceptions is only one part of the equation. When something throws, then you need something to catch! Therefore, as said: balancing comes in. Whatever you do in your code has to "add value" to it. If your code doesn't fulfill a clear, defined purpose, then chances are: you don't need it!
Upvotes: 4