3 ms·
How is an exception different from “returning an error message”?
by layer8 1y ago
How is an exception different from “returning an error message”?
- dewey 1y agoSeems like the main differentiator is that one crashed and one doesn’t. Unrelated to error message or exception.
- radlad 1y agoI'm not sure I understand how both occurred at once. Typically an uncaught exception will result in a crash, but this would generally be considered an error at the call site (i.e. failing to handle error conditions.)
- layer8 1y agoI understood “crashing” as them not catching the exception. Most functions can fail, and any user-facing app has to be prepared for it so that it behaves gracefully towards the user. In that sense I agree that the error reporting mechanism doesn’t matter. It’s unclear though what the difference was for the GP.
- ToucanLoucan 1y agoFor one: terminating execution More importantly: why is having more than one account an "exception" at all? That's not an error or fail condition, at least in my mind. I wouldn't call our use of the framework an edge case by any means, it opens a web form in which one puts authentication details, passes through the flow, and then we are given authentication tokens and the user data we need. It's not unheard of for more than one account to be returned (especially on our test devices which have many) and I get the one-account function not being suitable for handling that, my question is... why even have it then, when the multi-account one performs the exact same function, better, without an extra error condition that might arise?
- TOGoS 1y ago> why is having more than one account an "exception" at all? That's not an error or fail condition It is if the caller is expecting there to be exactly one account. This is why I generally like to return a set of things from any function that might possibly return zero or more than one things. Fewer special cases that way. But if the API of the function is to return one, then you either give one at random, which is probably not right, or throw an exception. And with the latter, the person programming the caller will be nudged towards using the other API, which is probably what they should have done anyway, and then, as you say, the returns-one-account function should probably just not exist at all.
- lazide 1y agoChances are, the initial function was written when the underlying auth backend only supported a single account (structurally), and most clients were using that method. Then later on, it was figured out that multiple accounts per credential set (?!?) needed to be supported, but the original clients still needed to be supported. And either no one could afree on a sane convention if this happened (like returning the first from the list), or someone was told to ‘just do it’. So they made the new call, migrated themselves, and put in a uncaught exception in the old place (can’t put any other type there without breaking the API) and blam - ticket closed. Not that I’ve ever seen that happen before, of course. Oh, and since the multi-account functionality is obviously new and probably quite rare at first, it could be years before anyone tracks down whoever is responsible, if ever.
- layer8 1y agoThere’s no good way to solve this, though. Returning an arbitrary account can have unpredictable consequences as well if it isn’t the expected one. It’s a compatibility break either way.
- lazide 1y agoExactly, which is probably why a better ‘back compatibility’ change couldn’t be agreed on. But there is a way that closes your ticket fast and will compile!
- kfajdsl 1y ago> For one: terminating execution Seems like you should have a generic error handler that will at a minimum catch unexpected, unhandled exceptions with a 'Something went wrong' toast or similar?
- zahlman 1y ago> For one: terminating execution Not if you handle the exception properly. > why is having more than one account an "exception" at all? That's not an error or fail condition, at least in my mind. Because you explicitly asked for "the" account, and your request is based on a false premise. >why even have it then, when the multi-account one performs the exact same function, better, without an extra error condition that might arise? Because other users of the library explicitly want that to be an error condition, and would rather not write the logic for it themselves. Performance could factor into it, too, depending on implementation details that obviously I know nothing about. Or for legacy reasons as described in https://news.ycombinator.com/item?id=44321644 https://news.ycombinator.com/item?id=44321644 .
- wat10000 1y agoThe iOS UI languages (ObjC and Swift) have three different mechanisms that are in the realm of exceptions/errors. ObjC has a widespread convention where a failable method will take an NSError** parameter, and fill out that parameter with an error object on failure. (And it's also supposed to indicate failure with a sentinel return value, but that doesn't matter for this discussion.) This is used by nearly all ObjC APIs. Swift has a language feature for do/try/catch. Under the hood, this is implemented very similarly to the NSError* convention, and the Swift compiler will automatically bridge them when calling between languages. Notably, the implementation does not do stack unwinding, it's just returning an error to the caller by mostly normal means, and the caller checks for errors with the equivalent of an if statement after the call returns. The language forces you to check for errors when making a failable call, or make an explicit choice to ignore or terminate on errors. ObjC also has exceptions. In modern ObjC, these are implemented as C++ exceptions. They used to be used to signal errors in APIs. This never worked very well. One reason is that ObjC doesn't have scoped destructors, so it's hard to ensure cleanup when an exception is thrown. Another reason is that older ObjC implementations didn't use C++ exceptions, but rather setjmp/longjmp, which is quite slow in the non-failure case, and does exciting things like reset some local variables to the values they had when entering the try block. It was almost entirely abandoned in favor of the NSError* technique and only shows up in a few old APIs these days. Like C++, there's no language enforcement making sure you catch exceptions from a potentially throwing call. And because exceptions are rarely used in practice, almost no code is exception safe. When an exception is thrown, it's very likely the program will terminate, and if there happens to be an exception handler, it's very likely to leave the program in a bad state that will soon crash. As such, writing code for iOS that throws exceptions is an exceptionally bad idea.