
RuntimeExceptions – To try-catch or not to catch? - perseus323
http://10kloc.wordpress.com/2013/03/09/runtimeexceptions-try-catch-or-not-to-catch/
======
stickfigure
Sorry, this is not going to be gentle.

This post is clearly written by someone who is new to Java, and starts with
the antique assumption that the runtime/checked exception dichotomy is a good
idea. After nearly two decades of experience, programmers and language
designers have resoundingly voted this language design feature to be a
failure. A little bit of experience catching idiotic exceptions like
UnsupportedEncodingException and you start to see why. But it goes deeper than
just bad design in the standard libraries - checked exceptions fundamentally
violate interface encapsulation - try throwing a meaningful exception through
Runnable or Iterator. The net result is stacktraces with dozens of wrapped
exceptions that destroy any hope of meaningfully handling known error
conditions.

Stop it. JUST STOP IT. Checked exceptions have wasted hundreds of hours of my
time, not just writing lame wrappers so that I don't have to type try/catch on
every line of code, but also by making debugging and error handling five times
more painful than it should be.

If you're still touting checked exceptions in 2013, you are _part of the
problem_. Stop it. Java needs to evolve, and your fresh-from-1995 opinion is
not helping.

TL;DR: Of course you should catch RuntimeExceptions. There should be _no other
kind of exception_.

~~~
pifflesnort
> _checked exceptions fundamentally violate interface encapsulation_

You have that backwards. Unchecked exceptions will blithely and without
warning completely explode your stack. They're the Atomic Goto.

The only way to know whether you're going to get one is to check the
documentation, where you can only hope that the API author -- and the author
of every API he calls -- has actually documented the exceptions that get
thrown, because the compiler will be no help whatsoever, and god forbid an API
start throwing an exception later.

> _... try throwing a meaningful exception through Runnable or Iterator._

If you pass around an object that conforms to Iterator, but throw an exception
within it, __YOU'RE BREAKING THE API CONTRACT.__

Anyone that relies on the API contract of the Iterator class could have their
state completely walloped by the Atomic Goto you inserted with a runtime
exception.

> _Stop it. JUST STOP IT. Checked exceptions have wasted hundreds of hours of
> my time, not just writing lame wrappers so that I don't have to type
> try/catch on every line of code, but also by making debugging and error
> handling five times more painful than it should be._

This makes no sense, because _more_ work is required without checked
exceptions.

Without checked exceptions:

\- You must check the API docs for every line of code you write to see if it
will throw an exception, and if so, what types.

\- If it throws an exception, you must either add a try/catch block to handle
the error appropriately (or wrap it in a new exception type), or you must add
documentation to your method to declare that _it_ will bubble up an exception,
and of what type.

\- If new exception types are thrown by underlying code, nothing tells you
until your application explodes.

With checked exceptions:

\- The compiler tells you what exceptions code throws, and of what type.

\- If it throws an exception, you must either add a try/catch block to handle
the error appropriately, or declare it in the method prototype. The IDE will
do both of these things for you.

\- If new exception types are thrown by underlying code, the compiler will
warn you.

> _If you're still touting checked exceptions in 2013, you are part of the
> problem. Stop it. Java needs to evolve, and your fresh-from-1995 opinion is
> not helping._

Stop advocating broken API design and ignorance of API invariants.

~~~
stickfigure
I will try to follow the HN ethos and give you the benefit of all the doubt I
can. I have to admit, as someone who has been working with this language since
the beginning, it's a deeply frustrating struggle. This debate is a microcosm
of exactly what went wrong with Java, and why "kids these days" are abandoning
it in droves. Have you noticed that all the post-Java languages, from C# to
Ceylon, abandon this misfeature?

Point by point:

 _Unchecked exceptions will blithely and without warning completely explode
your stack._

No. They rewind back to the level at which you catch the appropriate exception
- possibly Exception. It's true that you aren't always able to catch each
exception as specifically as you want. But at least you have a hope of doing
that instead of catching RuntimeException and searching back through a dozen
nested exceptions, which _is today's reality_.

In actual practice, there's usually a place you can (and should) catch
Exception so that you can log and either retry or abandon the unit of work. In
the context of a web server, this is usually "one request". That's why your
appserver doesn't crash when something goes wrong.

This isn't theory, your appserver _already does this_ , and it's a wonderful
thing. Try doing some node.js programming sometime for a taste of what it's
like without that.

Your mistake is believing that there is an alternative to RuntimeException.
There is not.

 _If you pass around an object that conforms to Iterator, but throw an
exception within it, __YOU'RE BREAKING THE API CONTRACT.___

Again, your mistake is believing there is an alternative. With the exception
of very simple classes, _all_ code has exceptional conditions. Do you create
DatabaseIterator which throws DatabaseException (and NetworkException) every
time you want to iterate a result set? Then you can't use it with Guava or any
of the other 10 million Java libraries that consume standard interfaces, and
you might as well not have interfaces at all.

Only pedants care if the compiler checks every single exception. Real-world
programmers expect that code will complete normally, and catch exceptions at a
high enough level that they can do something useful about it (eg, retry or
return an error code to the client).

Exceptional conditions cannot be part of the API contract, because every body
of code has different exceptional conditions, and if you try to account for
them, you have one of two results:

* You give up on standard interfaces completely. You have DatabaseIterator (which doesn't extend Iterator), FileIterator (which doesn't extend Iterator), etc.

or:

* You throw IteratorException from each method. This is what the Java SDK ends up doing in various places (eg, InvocationTargetException) which is just plain retarded. It would make more sense (and be less annoying) to just throw Exception and leave off the wrapper exception.

 _You must check the API docs for every line of code you write_

Sorry, you are not excused from this, ever. At least with exceptions, you have
the option of ignoring the problem at deep levels and catching them higher up
- which you already have to do anyways, because nobody wants their app to
crash at the first exception. In webapps or appservers it's at the request
level; in GUI apps it's usually the UI event handler.

 _With checked exceptions:_

No, the compiler doesn't do any of that shit. Because in the Real World, you
end up passing data through a standard interface and the exception gets
wrapped. Don't believe me? When was the last time you saw a stacktrace that
_wasn't_ wrapped with several Caused by clauses? With the exception of remote
API calls (where the exception class may not exist on the client), Caused by:
is a fundamental failure of language design. There's no sane reason for this
construct to exist. Try writing code in other languages and feel how
refreshing it is to get clean stacktraces. You don't even have to leave the
JVM, you just have to use _any_ of the languages designed since 1995.

~~~
pifflesnort
I am having a lot of trouble giving you the benefit of the doubt, since what
you seem to be arguing for is leaving API contracts completely ambiguously
defined because it's too much effort for you to do otherwise. You're not
arguing for correctness, or for reliability, but rather for your own
convenience in the face of something you find burdensome. That is
uninteresting to me.

This subject has been hashed to death, we're repeating the same arguments. You
want to leave things ambiguous, I want to ensure that behavior is well-
defined.

You're right that this has been abandoned by other languages. In many of those
languages -- including Scala -- you can make use of Either/Option monads to
achieve the same effect without exceptions at all. In others, you just have to
either expend a bunch of mental effort to ensure you code defensively, or take
your approach of spinning the chamber and hoping for the best.

Your argument for "well defined points" only begins to make sense in purely
functional languages. Otherwise, there's no way to guarantee a lack of side-
effects in your use of atomic-goto, and the result is _invariably_ that the
software is unreliable and prone to strange stateful failure.

~~~
jontro
Working with the org.json.JSON classes is what made me switch my mind about
the use of checked exceptions. Catching these checked exceptions makes no
sense at all.

~~~
pifflesnort
That API in particular has 'opt' variants of its accessors that return NULL
rather than throwing an exception.

That said, a standard clean usage model for the checked variants would be to
declare a 'throws' from your JSON parsing code, and then at a higher level
wrap that in an InvalidMessageException or similar. The non-checked approach
would be to check for NULLs and ensure that none escape your parsing code.

The only time the checked version becomes burdensome is if you don't
encapsulate your JSON -> app model parsing in a single place, and instead
sprinkle the code with unencapsulated JSON parsing. In that case, I believe
the problem is a lack of encapsulation, not the checked exceptions -- the
exceptions just highlights that one is not separating concerns between code
that must be aware of parsing issues and potentially invalid data, and code
that can be guaranteed to only operate on valid and whole data.

------
pjungwir
I think it's normal to catch RuntimeExceptions at a high level in your outer
loop so you can log it, email it, or whatever, and not let your process die.
This is what servlet containers like Tomcat are doing. I agree that catching
them elsewhere raises suspicions.

The author's example seems fine, provided they can distinguish an exception-
from-a-B-transaction vs an exception-from-a-program-bug. If I were him, I'd
keep that checkFormat method, but only call it when I catch a
RuntimeException, to see if it's something to worry about or not.

I was pleased that the author appears to have tested the performance of both
approaches and is making a decision based on real numbers.

------
smoyer
I'd love to be able to say I _never_ have to catch RuntimeExceptions, but that
would require that library and framework writers actually use checked
exceptions when they should. The best example I can think of (and one that a
JEE developer who uses JPA should be intimately familiar with) is that that
the getSingleResult() method of the Query object in JPA throws
RuntimeExceptions if zero or more than one result is returned.

~~~
suresk
The funny thing is, in almost any discussion about exception handling in Java,
I hear the opposite complaint - too many APIs throw checked exceptions. I've
been leaning more and more to liking it when APIs force consumers to at least
be aware of known error conditions.

Scala's _Option_ type is another example of this - I've watched people be sort
of annoyed by it at first, but it tends to really improve the reliability and
overall quality of the code when it is used properly.

~~~
lucian1900
Scala's Option is a monad, so it's very easy to chain several actions and
safely decide if they all succeeded or failed. It doesn't compare with checked
exceptions at all.

------
traxtech
In "real life" you catch runtime exceptions everywhere, because well, that's
what third-party libraries often throws. I hate that, especially when these
exceptions occurs in prod...

------
Uchikoma
Runtime exceptions can turn into ugly production problems. I prefer a
combination of Validation, Success/Failure, Some/None and checked exceptions.

------
aardvark179
I strongly agree that runtime exceptions are the right way to go for certain
rare events, see for example the new Java 8 addExact and multiplyExact methods
which throw exceptions on overflows. These will not happen often but making
them an exception allows implementers of languages with numeric type promotion
to remove their own checks, and for the JIT to optimise the entire exception
away in most cases.

------
jhdevos
Of course, there are also the RuntimeExceptions that should really have been
just Exceptions. These are often thrown by libraries where new features
required exceptions to be thrown, but they couldn't be checked exceptions
because the interface had to remain backwards compatible...

Or, of course, libraries written by people who just don't like checked
exceptions at all.

------
jontro
It seems that the debate about using checked or unchecked exceptions is still
running.

This article has some more insights I think
[http://jyops.blogspot.se/2012/03/why-should-you-use-
unchecke...](http://jyops.blogspot.se/2012/03/why-should-you-use-unchecked-
exceptions.html)

------
rfxtr
Awesome post. Thanks for posting. This was my interview question.

