Earlier quoted context omitted.
Exception based error handling is unsafe when they are unchecked exceptions. Checked exceptions however are as safe as Either, Try, Monads, Applicatives or whatever. You are forced to declare them in your method signature, the caller is forced to either handle them or rethrow them + declare them as well. And I guess this is precisely why so many developers hate them; they don't like the extra work they have to do to…
> Checked exceptions however are as safe No. If I add a checked UserNotFound exception to a getUser db call, you can bet someone higher up the stack will do try catch Exception e, so now they're catching OutOfMemory and who knows what else.
Unchecked Java: Say goodbye to checked exceptions
71–80 of 297 posts
Re: Unchecked Java: Say goodbye to checked exceptions
#72Earlier quoted context omitted.
The problem with that is you lose all ability to understand or control what a given endpoint will return in any given situation > I have no specific error handling for the given problem then pass it on and decide what to do with it at the system boundary in the db: fun getUser(uuid: UUID) : Either middle layers: pass around the either, you can map, flatmap etc on it to chain it with other computations there then in t…
> The problem with that is you lose all ability to understand or control what a given endpoint will return in any given situation Why? In the simplest (but pretty common) case it's: - successful response - generic error message > then pass it on and decide what to do with it at the system boundary Yes, but if in 99% of cases I only pass it on, it's just visual noise. Noise you become blind to, and it loses meaning. >…
Your controller method cannot act differently on a DBConnectionerror or OutOfMemory error.
Not to mention that exceptions cause developers to use them as control flow mechanisms.
For example searching a user by id. If the database returns 0 records, is that reason to throw an exception? Well, doing result[0] results in IndexOutOfBounds due to result being [].
But the reality is that the user not being there isn't exceptional. Typos are common. By using Result or Either you enforce the developers to think more about their flow. One can write the method like this:
fn find_by_id(id: usize) ->Result -> {
let raw_db_result = db.search("SELECT id, first_name, last_name FROM user WHERE id = ?", id)?;
match raw_db_result {
None => Ok(UserResult::NotFound),
Some(r) => {
let only_user = r.ensureOneResult()?;
let user = mapDBUserToUser(only_user);
Ok(UserResult::User(user))
}
}
}
What about Error? Reality is that I don't really care. Error doesn't contain anything that is actionable. Either the whole chain succeeds and returns a valid result or the Error. The caller wants to find a user by id. There is one, or there isn't. All the rest is just errors that they'll pass on too. And in the end they get logged and result into Error 500.A 404 is actually a valid result.
Now, if I were to use a throw new UserNotFoundException() for no user found you end up with generic try catches catching too much. And now someone needs to go and take it all apart to identify that single Exception that they want to deal with separately.
Whereas if I want to add a state in my enum the callers _MUST_ update their code due to how Rust works.
Re: Unchecked Java: Say goodbye to checked exceptions
#73Earlier quoted context omitted.
Exception based error handling is unsafe when they are unchecked exceptions. Checked exceptions however are as safe as Either, Try, Monads, Applicatives or whatever. You are forced to declare them in your method signature, the caller is forced to either handle them or rethrow them + declare them as well. And I guess this is precisely why so many developers hate them; they don't like the extra work they have to do to…
> Checked exceptions however are as safe No. If I add a checked UserNotFound exception to a getUser db call, you can bet someone higher up the stack will do try catch Exception e, so now they're catching OutOfMemory and who knows what else.
But that's laziness on the caller's part. If I offer a method but the caller decides to do reckless lazy crap with it, there are many different ways to get there in any language. I typically call those out (Exception e) at code reviews.
Re: Unchecked Java: Say goodbye to checked exceptions
#74Earlier quoted context omitted.
> Checked exceptions however are as safe No. If I add a checked UserNotFound exception to a getUser db call, you can bet someone higher up the stack will do try catch Exception e, so now they're catching OutOfMemory and who knows what else.
OutOfMemoryError isn't an exception so they would not be catching it.
Re: Unchecked Java: Say goodbye to checked exceptions
#75Earlier quoted context omitted.
> Checked exceptions however are as safe No. If I add a checked UserNotFound exception to a getUser db call, you can bet someone higher up the stack will do try catch Exception e, so now they're catching OutOfMemory and who knows what else.
> you can bet someone higher up the stack will do try catch Exception e But that's laziness on the caller's part. If I offer a method but the caller decides to do reckless lazy crap with it, there are many different ways to get there in any language. I typically call those out (Exception e) at code reviews.
Re: Unchecked Java: Say goodbye to checked exceptions
#76Earlier quoted context omitted.
> The problem with that is you lose all ability to understand or control what a given endpoint will return in any given situation Why? In the simplest (but pretty common) case it's: - successful response - generic error message > then pass it on and decide what to do with it at the system boundary Yes, but if in 99% of cases I only pass it on, it's just visual noise. Noise you become blind to, and it loses meaning. >…
It feels like you're trying to use Exceptions as a way to steer your logic, otherwise why would you need to know why an operation failed to such detail? Your controller method cannot act differently on a DBConnectionerror or OutOfMemory error. Not to mention that exceptions cause developers to use them as control flow mechanisms. For example searching a user by id. If the database returns 0 records, is that reason to…
Re: Unchecked Java: Say goodbye to checked exceptions
#77Exception based error handling is so bad and unsafe that adopting functional error handling with Either, Try etc as implemented by functional addon libraries for many languages, while not yet common, in time it will become the new default even in OO languages. (just like it's been the default in functional languages for decades) Functional error handling types are much simpler, safer and more powerful. Simpler becaus…
> Safer because unlike exceptions, they force callers to handle all potential outcomes, but no more. Which is bad. In 99% of cases I have no specific error handling for the given problem. Just let the process crash or be handled by application server / framework. Representing these kinds of error conditions in the code which I have no interest in handling is just noise.
Re: Unchecked Java: Say goodbye to checked exceptions
#78I actually quite like checked exceptions, and miss them in other languages. My biggest gripe with exceptions is that a few calls deep, you can no longer tell whether calling something might throw or not, and what type of exception it might potentially throw.
I like checked exceptions in principle too, but Java's implementation of them is so bad that I hate them there. The first major mistake is that it doesn't support exception polymorphism (e.g., I wish you could pass a comparator to Arrays.sort that throws checked exceptions, and have that call to Arrays.sort itself then throw the same checked exceptions), and the second is that the standard library makes a bunch of ex…
Re: Unchecked Java: Say goodbye to checked exceptions
#79Earlier quoted context omitted.
OutOfMemoryError isn't an exception so they would not be catching it.
whatever, the point is exception allows and encourages people to catch less and more than they should
Re: Unchecked Java: Say goodbye to checked exceptions
#80Earlier quoted context omitted.
> The problem with that is you lose all ability to understand or control what a given endpoint will return in any given situation Why? In the simplest (but pretty common) case it's: - successful response - generic error message > then pass it on and decide what to do with it at the system boundary Yes, but if in 99% of cases I only pass it on, it's just visual noise. Noise you become blind to, and it loses meaning. >…
It feels like you're trying to use Exceptions as a way to steer your logic, otherwise why would you need to know why an operation failed to such detail? Your controller method cannot act differently on a DBConnectionerror or OutOfMemory error. Not to mention that exceptions cause developers to use them as control flow mechanisms. For example searching a user by id. If the database returns 0 records, is that reason to…
I'm not defining the errors like DBConnectionError or OutOfMemoryError - it's the framework/platform which defines them and throws/returns them.
> But the reality is that the user not being there isn't exceptional.
That depends. In some contexts it is not exceptional (getting user by ID given as an argument to webservice), in that case using Maybe type is great. In other contexts it is very much exceptional (e.g. signed JWT refers to a non-existing user) and throwing Exception makes more sense.
> What about Error? Reality is that I don't really care. Error doesn't contain anything that is actionable. Either the whole chain succeeds and returns a valid result or the Error. The caller wants to find a user by id. There is one, or there isn't. All the rest is just errors that they'll pass on too. And in the end they get logged and result into Error 500.
Which is the same as exception. But now you have this visual noise of something you claim you don't care about. An unchecked exception makes this irrelevant noise go away.
> Now, if I were to use a throw new UserNotFoundException() for no user found you end up with generic try catches catching too much. And now someone needs to go and take it all apart to identify that single Exception that they want to deal with separately.
try {
...
}
catch (UserNotFoundException e) {
// handle ...
}
I'm catching exactly the exception I want. Where I'm catching too much? Where do I need to take it apart?(This particular example of exception usage is bad, though, as it smells of exception control flow. Here using Maybe type would be better)
> Whereas if I want to add a state in my enum the callers _MUST_ update their code due to how Rust works.
Which is good for some cases where the enum describes "business" cases.
But it is pretty bad for truly exceptional cases (which are unlikely to be handled anyway). Library adding a new exceptional case will break its clients, which seems like a bad trade-off (again, for truly exceptional cases).