Fork me on GitHub

It seems like some languages, frameworks, designs… especially in java, lean towards throwing exceptions in places i find questionable. For example, if a http request is a 500, i have seen systems raise an exception. I find this very odd, as what 500 implies for the caller seems perfectly natural. Like, i made a request, the person on the other end has told me their was a problem, why would I choose to potential halt on an event I have to handle. I guess i’ll put it this way, i can’t understand ever needed to raise an exception that would be caught in the same program. At that point i feel were using exceptions as another way to manage state in a program only with the added headache of making this more obscure in failure.


Throwing an exception typically means "I can't handle this (unexpected) situation" (but maybe something up the call tree can).


In the HTTP service case, clj-http very specifically lets you throw exceptions on non-success status or choose to handle it. Low-level code that is actually making the HTTP call may or may not know how to handle failure of that service, i.e., there may not be a sensible result it can return to its caller when the HTTP service fails. Or it may be able to handle some non-success status codes but not others -- so it needs a way to distinguish between "it failed in an expected way and here's the result" vs "it failed in an unexpected way -- I'm giving up!".


You're definitely right that a lot of Java code seems to lean on exceptions for both unexpected and expected failures -- and part of that is because, in Java, thrown exceptions are part of a function's type signature (and if a function throws something it hasn't said it could throw, you get a runtime error instead). And Java has two complete hierarchies of exceptions: Exceptions and Errors -- the latter are generally the unexpected failures and, in Java at least, the former are generally treated as "expected" failures.


I usually use exceptions to handle cross-cutting failures that can occur at any point within a given module, and is for communicating failure outside that module. It is less explicit than explicit error return types, at the benefit of not having to weave error types through every component.


(I used to push for checked exceptions, but Java's implementation is just dysfunctional enough to make it very frustrating to use, especially w/ Java 8 and lambdas.)


It's good, I think, to consume a breadth of opinions on exceptions and the philosophy of their use - Erlang, for example, can leverage 'fail fast' exceptions much more literally and reliably than a language like Java that can't visibly control the scope of failure.