
Exceptions are Bad - chrisbroadfoot
http://blogs.atlassian.com/developer/2011/05/exceptions_are_bad.html
======
jakevoytko
Exceptions have a major advantage not mentioned by the OP.

In code, errors usually happen several stack frames away from the code that
knows how to recover. The network can't transmit data because a remote
computer doesn't respond[0], so it passes an error to the network library,
which passes an error to an RPC dispatcher, which passes an error to the high-
level RPC interface, which finally produces an error at the site of your RPC
call, where you can decide what to do.

If you don't have exceptions, you must write all of this error handling code
yourself. Plus, if you need to pass the error higher than the call site to
make a good decision, you must write that too. However, if you have
exceptions, you can avoid writing most of the error passing code, and you can
group error handling logic in the same place. You get more flexibility in
structuring and refactoring your code, in exchange for encountering problems
when things unexpectedly go out of scope.

[0] This certainly passes my 'exceptional circumstance' threshold, since
success is no longer possible.

------
dexen
Let me get this straight: he's doing a a full circle -- _without_ examining
how the current situation came to be.

At some point we went for exception, because (warning: big simplification
ahead!) library authors figured they can't trust client code to always check
return value for reported error condition. We got automatic, forced checking
injected by compiler -- `exceptions'. With all the pains of _fugly_ syntax in
certain languages, because in many projects the trade-off makes sense. With
the reasonable default for unexpected and unhandled condition: error is logged
and process is stopped.

Now the proposal -- `Let's have [[EDIT]]a tagged union: Either<error_code,
return_value> ' takes us back to where we started -- client code is free to
not check for errors. The process will not stop nor even print backtrace if
the programmer forgets to check; the process will happily go on with invalid /
unsupported / mangled / whatever data. No automatic propagation of error down
the stack to outer handler in our function's caller. No stack unwind nor
automatic object destruction. No hierarchy of error types (no specific errors
derived from general ones). No nothing. And _no discussion_ of those matters.

Oh, my. Reliability in software has just gotten a new name.

EDIT: fix'd mistake pointed out by tianyicui & thesz. Thanks!

~~~
tianyicui
> [...] client code is free to not check for errors. The process will not stop
> nor even print backtrace if the programmer forgets to check; the process
> will happily go on with invalid / unsupported / mangled / whatever data.
> [...]

This statement is simply not true, at least in languages that actually have
Either data types (read: Haskell). But I'm not sure how to implement the
generic class Either in Java.

~~~
dexen
Please elaborate on how it works? Perhaps I got this very wrong; never used an
Either<> class.

Would an attempt to access the value (if an error was indicated instead) cause
error condition? Would it be similar in nature to an exception?

~~~
masklinn
> Would an attempt to access the value (if an error was indicated instead)
> cause error condition? Would it be similar in nature to an exception?

Either is a tagged union (actually a sum type), you have a value OR an error,
which are typed (haskell uses Left and Right as the constructors for Either,
by convention Left holds an error and Right holds a value, because right is
correct).

You can not just "cast" your Either, you have to type-check it with a case (or
use monadic operators) to unwrap it, and with the right flag the compiler will
ensure you're not missing cases. At compile time.

Either is basically Schrödinger's box (the computation resulted in both a
value and an error), and the compiler checks that you're set for handling both
a dead and a live cat, or it will not let you open the box.

~~~
dexen
Thanks for explanations; now it makes sense to me.

Another question: is there built-in support, or an idiom or standard practice
for unwinding multiple levels of stack? Is it possible to have handler code is
not directly in the function that called, but somewhere lower on the call
stack -- and have it reached automatically like an exception does?

Btw., it seems the bolder statement I post to HN, the wronger it turns out to
be... oh, boy XD

~~~
masklinn
> Another question: is there built-in support, or an idiom or standard
> practice for unwinding multiple levels of stack? Is it possible to have
> handler code is not directly in the function that called, but somewhere
> lower on the call stack -- and have it reached automatically like an
> exception does?

Not that I know, but I am very much a haskell novice. You may want to ask for
further information in /r/haskell, on reddit.

------
henrikschroder
_Now we have a more honest result type. It tells you that it will definitely
for each and every String return you something, either the Integer value or a
NumberFormatValidation (or an ErrorMessage, or an error String or whatever).
There is no null to deal with anywhere and no ugly catch blocks._

Is there really a significant difference between:

    
    
      Either<Bad, Good> result = callMyFunction(foo, bar);
      if (result.getBad() != null) {
          //Handle error
      }
      //Do something with result.getGood();
    

...and the regular:

    
    
      try {
          Good result = callMyFunction(foo, bar);
          //do something with result;
      } catch (Exception e) {
          //Handle error
      }
    

The first example is one line shorter, yay, but if you want to "throw" your
error upwards, you have to convert that Bad object into whatever is the error
class for your current scope and return that. Did you really gain anything
here? Or does the Either class have some extra magic on it that makes this
unnecessary?

~~~
mechanical_fish
Your example is too simple. Yes, if what you want is the exact same semantics
that you get with exceptions, Either is little better than exceptions.

I believe the trick with Either is that it assists one in designing completely
different strategies. For example, you can design plugins that accept
ambiguous arguments. Sometimes -- often, actually -- you really want to write
this:

    
    
        user_photo = load_user_photo(username)
        ui.display_user_page(username, user_photo)
    

but instead you are compelled to write something like this:

    
    
        try {
          user_photo = load_user_photo(username)
        } catch (PhotoFormatException e) {
          ui.tell_the_user_the_format_is_bad
          user_photo = NULL
        } catch (Exception e) {
          if (ui.interactive?) {
            ui.tell_the_user_a_terrible_error_occurred(e)
          }
          unless (ui.app_in_production?) {
            throw new MyScopeException(e, "bug")
          }
        }
        if (is_null(user_photo)) {
          ui.display_user_page_without_photo(username)
        }
        else {
          ui.display_user_page_with_photo(username, user_photo)
        }
    

(Now, I wrote that in an extra-clumsy way, but only so that we might fully
appreciate the clumsiness of the logic. In the real world, I'd probably try to
do this more elegantly. The result would probably (a) look cleaner; (b) be far
more abstract, confusing, and overdesigned than it needed to be; and (c)
contain a half-implemented broken implementation of the Either pattern. ;)

What we have here is an application that might need to behave differently if
there is a photo or not, and differently if the user is a production customer,
a script running in production, or a developer running on a local machine. And
because exceptions behave like exceptions whether I like it or not -- they
always travel up the stack, they're always in a panic -- that try/catch logic
has to be here, at this level.

But if load_user_photo() could return an Either I could just pass that Either
to ui.display_user_page(). And then I could plug in a "ui" class that does
something like this [1]:

    
    
        class Ui {
          function display_user_page(username, user_photo) {
             # The customer is blind; user_photo is irrelevant. 
             say("The username is " + username)
          }
        }
    

Or this:

    
    
        class Ui {
          function display_user_page(username, user_photo) {
             print("The username is " + username)
             if user_photo.is_good?() {
               display_photo(user_photo)
             }
          }
        }
    

Or this:

    
    
        class Ui {
          function display_user_page(username, user_photo) {
             if user_photo.is_bad?() {
               throw new HorrorException("I am shocked")
             }
          }
        }
    

or whatever you like. This logic doesn't necessarily belong in your main
logic, it belongs in a plugin, and the Either pattern helps you send it there.

\---

[1] These are oversimplified examples too, of course. In the real world my
class would probably do a little more exception handling. There is a certain
amount of irreducible pain in dealing with the infinite number of things that
might go wrong; all the language can do is give us the flexibility to organize
the resulting pile of code as best we can.

~~~
kstenerud
So basically an Either is for returning a different (ostensibly error) type in
a language that normally cares about the declared return type in a method
signature?

How would that work for passing the result to another method for analysis?
Relax the rules there too? Wouldn't that require doing away with
compiler/interpretor type enforcement altogether? (not that I have a problem
with that)

~~~
prodigal_erik
The type checker will confirm that other function accepts a (Either Bad Good)
as its argument. If you want to use a function that only takes a Good and
returns a SomethingElse, call it in a "do" block and the call will be skipped
if you got a Bad (because in the Either monad, the Left value is used for
short-circuit failure) or use liftM to convert it to a function that takes a
(Either Bad Good) and returns a (Either Bad SomethingElse).

A lot of other languages had to bake in exception type checking as a weird
special case, because even though the type of a function (because that's
really about when you can and cannot use it) should depend on which exceptions
it handles, they made that way too much hassle to actually enforce.

However, Haskell is still evolving, and people have also added a couple
versions of the typical bypass-the-type-system exception trainwreck, for
reasons that escape me.

[http://www.randomhacks.net/articles/2007/03/10/haskell-8-way...](http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-
to-report-errors)

------
Strilanc
I don't agree that returning an Either is better than returning/throwing. It
depends on what you do in the error case. If you try to recover, then Either
is better. If you fail fast, then throwing is better.

The main problem with checked exceptions, at least in Java, is the clumsiness
of doing things right. Ideally every function would expose exceptions
corresponding to useful error cases. Instead, because there's so much
boilerplate involved in creating new exception types and wrapping exceptions
as the proper type, programmers are more likely to swallow or blindly
propagate.

I believe making checked exceptions signifcantly better is as easy as adding
two features to Java:

\- Easy wrapping. 'wraps Type1 as Type2' for try blocks and function
signatures. \- Easy inline defining of new exceptions. 'throws forge
ParityMismatch extends IllegalArgumentException'

~~~
aidenn0
If you read the comments, the author wrote a comment that basically says this.
Exceptions should be used for fatal errors, not for recoverable errors.

------
thepumpkin1979
I think checked exception are indeed annoying, specifying what exception types
can be thrown in the method documentation it's pretty much enough. However I
don't think ugliness is the main reason why exception should be avoided as
much as possible, I think is _performance_ : You get a performance penalty
when you throw exceptions.

About the return values, since .NET 2.0 the TryParse calls were introduced and
it works pretty well in the case you don't need to know the details of a
failed parsing operation which I think is the 95% of the cases:

public static bool TryParse( string s, out int result )

I'm not saying we should stop using exceptions, but we should have more High
poerfomance alternatives like this in Java.

More info here: <http://msdn.microsoft.com/en-us/library/f02979c7.aspx>

~~~
benjiweber
This is a common dogma in .net land. If we're being fair a more accurate
statement would be "you _currently_ get a performance penalty when you throw
exceptions in _Microsoft's implementation_ of _.net_ ".

Exceptions are much faster in mono than Microsoft's .net[0], are much faster
still in Java[0] and can be made as fast as goto in Java in some
circumstances[1], particularly if you control the Exception class being
thrown.

Claiming Exceptions are slow is like saying "Java is slow". Languages and
language features aren't slow, implementations are.

[0]
[http://weblog.ikvm.net/PermaLink.aspx?guid=388b2a6d-e7b2-4ff...](http://weblog.ikvm.net/PermaLink.aspx?guid=388b2a6d-e7b2-4ffa-86e7-450c87e6178f)
[1]
[http://blogs.oracle.com/jrose/entry/longjumps_considered_ine...](http://blogs.oracle.com/jrose/entry/longjumps_considered_inexpensive)

~~~
thepumpkin1979
These are very interesting articles benjiweber and you are right, it depends
of the implementation. My point is that there are some cases in which you can
gain some speed by no throwing exceptions at all and TryParse is a perfect
example of this(at least in .NET). Also exception-handling blocks might
prevent the Virtual Machine from inlining the method(again, at least in .NET),
is this true for the JVM too?

------
troels
That was boring. I like Damien Katz' [epic piece about errors and
exceptions](<http://damienkatz.net/2006/04/error_code_vs_e.html>) much better.

------
PaulHoule
Errors are bad. Errors don't respect encapsulation. No amount of design work
will anticipate a SomebodyPouredACokeOnARouterInDetroit exception. If a system
is composable, there's alway the chance that some subsystem is going to throw
an error that wasn't anticipated.

Things like Either[A,B] make me cringe because they're just like what we used
to do back in the 1980's in C. You know, it used to be that you wanted to
write

int doAandB(x,y) { return A(x)+B(y); }

but then you had to deal with error values, and it turns out that A and B
never returned a negative integer so you'd write

int doAandB(x,y) { int a,b; a=A(x); if (a==-1) return -1;

    
    
        b=B(x);
        if (b==-1)
            return -1;
    
        return a+b; 

}

3 lines of code balloons to 9 lines of code. Read carefully: adding error
handling has tripled the size of this code sample!

That's what exceptions win for you... Effectively you get the extra 6 lines of
code written for you. You might argue that the default behavior of exceptions
might not be exactly what you want, but it's much better than the first
example I wrote... Aborting is a better default behavior than barreling past
an error.

Now, Either[A,B] is better than returning an in-band signal like -1, but still
requires you to write the bulky error handling code.

A real advantage of having something like Either[A,B] is when you're using
asynchronous communications. Just the other day, I was dealing with something
that used Scala actors and it turned out that sometimes the "business end" of
the actor would fail with an Exception. If you catch the Exception in the
actor and send it in a message to the next actor, it lets the next actor see
the Exception and decide what it wants to do about the failure.

As for variance of Exceptions, that's a pipe dream. Imagine a system that has
a subsystem that looks something up in a 'database'. That 'database' could be
an in-RAM lookup table (never throws exceptions), it could be an on-disk
lookup table (can throw IOException), it could be a web service (can throw
networking-related exceptions), or it could be using something like JDBC
(which could throw it's own exceptions).

If you constrain the kind of exceptions that can be thrown by the subsystem,
you either destroy the composability of the system or you 'dump-down' the
error information that's available to the executive level of the software.

Now, if you REALLY want to move forward but not back with composability of
error handling, what's needed is some mechanism that the executive level gets
'hints' that would help it deal with the error. That is, lets it answer
questions like:

(i) if I try this again immediately, is it likely that this will succeed? (ii)
if I try this again in five minutes, is it likely that this will succeed?
(iii) was this error caused by specific bad data I sent, or is this subsystem
in a completely failed state... etc.

~~~
jerf
"Things like Either[A,B] make me cringe because they're just like what we used
to do back in the 1980's in C."

In C(++/#), yes.

In Haskell, there's two absolutely critical differences, which are worth
pointing out, because while it's fun to raid Haskell for ideas it's important
to understand the context from which they come or you'll end up thinking good
ideas are just crazy. (I _want_ to see other languages raid Haskell, but it
ends up being very easy to copy the form and entirely, utterly miss the
substance. I see the same problem with Erlang copiers.)

First, the compiler forces you to unpack the error. Now, you can still write
code that discards the error or fails to handle it, but you can't simply
_forget_.

Second, you _can_ compose these together:

    
    
        bigOperation = do
            a <- eitherOperation
            b <- eitherOperation
            c <- someOtherEitherOperation
            return $ a + b + c
    

With the do notation in the Either monad, you'll get the first error in the
sequence, or the final result; you do not need to handle each error
individually. This is a choice you make on purpose; if you want to, you can,
if you want to handle errors in some other manner, you can, etc, this is not
"the" error handling technique in the language, it's just one that ships in
the base library. Personally I don't much like it because people tend to use
Either with a string in the error position, and I really hate it when strings
are the base error type.

(Also, there is a bit of a problem composing together different bits of code
that handle errors differently, which is a disadvantage of giving the
programmer so much flexibility. The exceptions mechanisms may not be perfect
but they are consistent.)

And, indeed, just copying the Either type into C(++/#) is copying the form and
missing the substance. I don't know what the solution for C(++/#) is, none of
those languages have rich enough abstraction to copy Haskell here.

~~~
jauco
IIRC in c# you can abuse selectmany and it's inline linq syntax to achieve
more or less the same effect. (google "monad selectmany" for examples)

------
russell
I am rather fond of the jQuery style of chaining method calls, which doesnt
work if methods return status codes. OTOH I dont like checked exceptions at
all. Mainly because development teams go overboard with an exception for every
type of problem. I make a call to a subsystem and I immediately have to deal
with half a dozen exception types so that I dont have to clutter up the
signature of my method. Especially in other peoples code where the exceptions
are just swallowed leaving behind "//TODO add logging".

The Either class looks like a reasonable alternative, although I would do it
slightly differently. Either<String> result = myMethod(). probably with a
different.

    
    
       result.getError();

would return some kind of error object

    
    
       result.getValue();

would throw an exception if there were an error.

It looks promising. I think I will play with it in Java.

~~~
masklinn
The problem here is that you can't really statically check your stuff.

With either and match completeness turned on, the compiler will _force_ you to
handle the error case, you have to "ignore" it very explicitly by doing
nothing in its handling.

------
brown9-2
What's the problem with returning _null_ from the Integer parse method,
provided that you _document_ when this method will return null? The author
dismisses this option without much of an explanation.

The aversion to using null for a return type here seems to be a symptom of the
same problem as throwing an unchecked exception - when the behavior isn't
probably documented, the developer isn't given a chance to know that the
return from the method needs to be handled.

But, if you can't trust developers to write or read documentation, then is it
really worth it to go out of you way to invent new ways of returning a non-
success response from this method? The underlying problem still exists - lack
of communication.

~~~
aidenn0
The problem with returning null is that you end up with an error in one part
of the code causing an exception in a later part of the code.

Integer i = foo(); //Do a bunch of stuff doSomething(i);

is _much_ harder to debug, especially if doSomething() is documented that it
is forbidden to call with a null. You now need to find where i came from,
which can be non-trivial.

If instead you return Either<SomeError,Integer> you now can't call a function
that hasn't contracted to either not unbox the value, or deal with the error.
It's making the type signature match the documentation, which means that the
compiler will help catch programmer error. I don't see how this can be
anything but a good thing.

------
coliveira
The main problem is to decide what really an exception is. One can make the
point that, in 99% of the cases, exceptions in a function should be handled as
predictable actions. If a correct client needs to deal with it, it is better
to use if/else than a try/catch clause. The later almost always makes to code
more obscure and difficult to understand. There is a reason why in
professional C programs most of the code goes to error handling: it is
necessary. The equivalent Java code will just have one try/catch per line of
code, or just let exceptions crash the app.

------
BruceForth
Gaaahh.... Just because C++ and Java do something incredibly stupid when it
comes to exceptions, doesn't mean exceptions are bad. Just that C++ and Java
suck.

(hint: exceptions without restarts are retarded)

------
jaekwon
Look at Node.js, where exceptions don't necessarily travel up written code,
begetting the convention of passing an error object, similar to what the OP
proposes.

I don't like it, I don't think anyone particularly likes it. It makes you miss
exceptions.

