• Flips (unregistered)

    Such a handy feature! I would suggest to implement Exception as a K61Exception, to extend functionality to all Exceptions! }

  • (nodebb)

    I confess, I see this as an example of bad naming. I'd probably have called it, "unrecoverable" or "isUnrecoverable" - a way of saying, "This exception you cannot recover from".

    Sadly, when doing DCOM or integrating to older languages, the only way to handle something has gone wrong is by a non-0 / exceptional result. You then have to pick through the exception type to determine - is this really something we need to blow up on, or is it a business-as-usual error (the user you passed in is unauthorised to perform this action, the user doesn't have enough funds, the user entered a duff URI for us to scrape... the list goes on).

  • ronin (unregistered)

    I have a feeling that they are misusing Exceptions as control flow (like for breaking out of a loop) and therefore need this flag.

  • akozakie (unregistered)

    Heh, this reminds me of some code one of my students once wrote. Call it "Exception is the rule" or "Function of no return" if you like. Recreating it from memory, so I'll stick to Java-like pesudocode.

    Problem - deep labyrinth of recursion and iteration digging around a large data structure in memory. How do you get out of this quickly once you've found/computed what you were looking for? Like this :

    // ... skipping the rest of class definition void doStuff(/some arguments/) throws SuccessException, NoDataException, SomeMoreExceptions { // do some stuff to prepare the job try { startWorking(/*some args */); } catch (Exception e) { throw e; } throw new NoDataException(); }

    Yes, really. Some exceptions might get legitimately thrown, that's an actual exception, so pass them out - this one's fine. Then we might not have been able to find the solution, in which case we throw a custom NoDataException - that's sort of ok, it's rare and there's no usable output, so yeah, it is an exception. And then you have the custom SuccessException, which actually stores the result(!) - it gets thrown once it's ready, collapses the call stack, and gets to our main function. That's not the right way to use exceptions, but it would be just an internal WTF if we unwrap the result and return it like a civilized method. But nooo, we don't do that stuff here! We just pass it out, leaving the task of extracting the result from the SuccessException.

    You read that right. This method never returns normally. It always throws something. Very rarely a normal exception, sometimes a custom but acceptable exception meaning "no result", usually the great beautiful SuccessException.

    The class name of that exception (yes, it actually WAS called SuccessException) has entered my dictionary as a synonym of WTF.

    Bonus points if you guessed that SuccessException actually extends Exception. I would have been a bit less irritated if it at least extended Throwable instead and was called something like ThrowableResult...

  • 516052 (unregistered) in reply to ronin

    I wonder how far you could go with that. Like, imagine a program structured around one giant dispatcher function that is entirely composed of exception handlers and a switch. And the rest of the program communicates with this function by throwing exceptions in order to invoke function calls like some sort of demented deformed event handler. Not that the idea would be good if it were done with event handlers. But cool none the less.

  • akozakie (unregistered) in reply to akozakie

    Gah, sorry for the unreadable code, forgot to mark it... I hope it still makes sense.

  • Prime Mover (unregistered)

    As code design goes, a little feeble. At the very least implement an enum, with values Bad, VeryBad, PrettyDamnBad, ReallyReallyBad, Nightmare, OhBugger.

    I did once have to maintain an application which had numerous error cases, all of which could be triggered by bad data, all of which passed control to an error branch, which printed out "oh bugger" and exited.

  • (nodebb) in reply to Peter Street

    I confess, I see this as an example of bad naming. I'd probably have called it, "unrecoverable" or "isUnrecoverable" - a way of saying, "This exception you cannot recover from".

    It more a fundamental misunderstanding of classes. Rather than an isUnrecoverable method, extends UnrecoverableException is "more OO". It's also more suited to how exceptions are caught; catch (UnrecoverableException) is much more readable than having a switch or if in a generic exception handler.

  • akozakie (unregistered) in reply to Jaime

    In general a really UnrecoverableException is would be an Error, a different Throwable, wouldn't it?

  • NoLand (unregistered)

    While I appreciate the approach, it's still a half-hearted effort. What is needed is the active complement, a method isNotAnException(), which makes the Exception go away. Every programmer should be provided with the means to answer back to realities that might be messing with their beautiful code!

  • (nodebb)

    I get the feeling the developer who named this flag may have been working under duress. They were forced, either by management or by existing designs, to use exceptions in unexceptional circumstances (or maybe this exception class was already in use before they added the flag, and they couldn't change that usage). They complied, but they managed to protest in some small way through the naming of the flag.

    If they had actually wanted to design the exception this way, they would have named the flag something like isError, isException',exceptionType, orb. The nameisReallyAnException` seems to say, "I acknowledge the stupidity of this flag, but here it is anyway."

  • (nodebb)

    Is this really a comment?

  • Foo AKA Fooo (unregistered) in reply to akozakie

    Though actually, what would you suggest? Let's take an extreme case, like various places of recursive calls, perhaps even indirectly though several functions, vs. one place where a result is found.

    The typical approach of returning the result level by level is just as cumbersome as non-exception-based error handling and may hurt performance. (Since recursion tends to exhibit exponential growth, performance may matter.)

    So with better inheritance and naming (such as "ThrowableResult"), and internal catching and unwrapping, is this so bad?

  • Carl Witthoft (google)

    Ceci n'est pas un Exception.

  • Anonymous (unregistered) in reply to Foo AKA Fooo

    I think the answer here is "It depends on the language".

    For example, Java, which this submission appears to be and the student's code almost certainly was (based on Throwable), has really heavy Exceptions/Throwables due to generating full stack traces on creation. (It is possible to prevent this by overriding fillInStackTrace(), but neither code likely did this; it's very obscure.)

    Python, on the other hand, uses exceptions for flow control as part of the language. (You exit a for loop by having the iterator raise StopIteration, for example). Exceptions are much lighter and more "expected" in Python, so it's natural there.

  • (nodebb) in reply to akozakie

    Error is reserved (or used to be reserved) for internal issues in the JVM. I would subclass RuntimeException which is also unchecked.

  • Foxglove (unregistered)

    There are various languages that abuse exceptions, and this is a workaround. You get loads of 'exceptions' that are expected and need to be filtered out of the logging.

  • Best Of 2021 (unregistered) in reply to Foo AKA Fooo

    Returning and propagating that result up the call stack is the right way to do it. Even with no optimisations it's likely to be more performant - exceptions are really expensive. If your recursive method can be optimised as tail recursion then returning up the stack will optimise away into a single return anyway.

  • Foo AKA Fooo (unregistered) in reply to Best Of 2021

    You're right about tail recursion, so let's assume no tail recursion possible for the hypothetical example. :)

    Exceptions may be expensive, but only by a constant factor. That's why I mentioned exponential growth (imagine a huge complex search and a single point of returning the result). A small overhead on each recursive call will easily outweigh any constant cost. Actually, the cost of returning the result by exception will probably be dwarfed by the cost of outputting (or otherwise using) the result.

  • Thomas Fjellstrom (github) in reply to ronin

    I've been dabbling in Intellij plugin work and it has a couple different control flow "exceptions". It even complains at you in the log if you log them yourself. I guess it is one way to semi force most plugin code to respect a cancel. Unless of course you try to catch all exceptions in your plugin so it doesn't cause really strange ide behavior and forget to pass the control flow exceptions on which itself will probably cause more strange behaviour (like not canceling a heavy operation when the ide or user asks for it).

  • (nodebb) in reply to Eric Ray

    I had the same feeling, like maybe they inherited this from someone versed in a language like Python where you inevitably end up dealing with lots of exceptions thrown by mundane operations that should be expected to occasionally fail as part of normal program flow, and are thus not really exceptional. So there end up being lots of catch blocks that need to decide if what went wrong needs to be handled as a true exception versus a BS fake exception that's really a mundane thing that you would have been able to guard against using a less severe mechanism given a more reasonable language/API/library.

  • Loren Pechtel (unregistered)

    Count me amongst those who think this is really sorting out the this-can't-be-done "exceptions" from the something-unexpected-happened situations for which you probably should terminate.

    The UnrecoverableException approach has been suggested and in most cases would be the best answer (but maybe not possible in legacy situations) but not all exceptions can be cleanly divided like that.

    /0 error? If your code throws a /0 you no doubt have odoriferous fertilizer in the air mover. But what if it's not your code? Plenty of systems support some form of user language and if that language supports division you could have a /0 error that simply means you scold the script-writer, you don't need to terminate the program.

  • (nodebb)

    I despise "non-exceptional" exceptions.... IF you can test for it, then you should test for it. Consider an input file that is needed.... Don't throw an exception if it dowes not exist.... CHECK and handle with flow control. Then if the open fails throw exception (it is exceptional that the file was deleted in the uS between the two events)

  • (nodebb)

    " If your code throws a /0 you no doubt have odoriferous fertilizer in the air mover." ... but does that make it "unrecoverable" to the point were termination of the program is needed? I would say that would be a minority of the cases.

  • holy shit now I'm actually commenting here... (unregistered) in reply to Foxglove

    I guess those are expections then...

  • holy shit now I'm actually commenting here... (unregistered) in reply to holy shit now I'm actually commenting here...
    try
    {
      // ...
    }
    expect (ThrowableResult r) // expection
    {
    }
    catch (NotFoundException e) // exception
    {
    }
    
  • (nodebb)

    I don't know Java well enough, but would a call to isReallyAnException() just end up endlessly recursing the function, until the system generates a StackOverflow exception? So checking why K61Exception was thrown, would end up throwing a StackOverflow anyway?

  • Naomi (unregistered) in reply to Nutster

    I don't know Java well enough, but would a call to isReallyAnException() just end up endlessly recursing the function, until the system generates a StackOverflow exception? So checking why K61Exception was thrown, would end up throwing a StackOverflow anyway?

    It wouldn't. isReallyAnException() is a method call; isReallyAnException, without the parentheses, is just a member variable. It's just like this:

    public boolean foo() {
        return bar;
    }
    

    ...except that the method and the variable happen to have the same names (which is fine, although it'd be more conventional to name the variable reallyAnException). Does that make sense?

  • Some Ed (unregistered) in reply to akozakie

    I'm reminded of a rash of success errors we had a while back.

    Our team does a lot of work with a database API that usually returns a result code of 0 for success. The only exception happens with an operation that we never use., as it's used to handle a niche case that our DBAs chose to not present us. We could still use it, but it's a pain, and easier to not.

    The API we use also provides us with an isError method, which helpfully determines whether the response was an error, regardless of what operation was performed. It's simple to use, and if one is not attempting to make ones script as blazingly fast as possible, it's kind of a no-brainer to use it. I mean, it's readable code, after all, so it's better than saying something like

    if (result.code()) { // do error handling here }

    But we had a bright bulb who thought he could get away with even fewer cycles than that.

    if (result.count()) { // do error handling here }

    But the thing is, returning no results is not an error when there's no matches. Also, their code was slower than

    if (int error_code = result.code()) { // do error handling here }

    Of course, there's also the thing that fast but wrong is not better than a microsecond slower but correct.

    Eventually, he retired in 2012, and his code was all purged of that particular issue. But of course there's still others, as I found earlier today.

  • fa (unregistered) in reply to TheCPUWizard

    I'm firmly on the other side, but then again, I use python. Opening an existing file is a perfect example of when using the exception leads to more succinct and / or more correct code. You don't care whether the file existed 5 microseconds ago, that's irrelevant to the program.To be correct, you have to handle the case where the file disappears before you can open it, anyway. (On NFS, the check will also lead to additional, unnecessary protocol operations)

    Maybe StopIteration (as menitoned by Anonymous) is pushing it a bit, but otherwise it's very useful and expressive to treat any small hiccups like that as exceptions. It would be great for atomic operations in multi-threaded programs, but Python isn't good with multi-threading.

  • JC (unregistered)

    Unless it's called from generated code, it's a WTF.

    I used to maintain a compiler that used an "uncaughtable" exception to implement continuations. Scala does some trickery with exceptions when you need to generate code for a non-local return statement.

    In such cases, you might see something like this.

  • Ruts (unregistered) in reply to fa

    I agree too - as the file-open operation will effectively check the file exists at the time it is used, and throw a suitably-named exception if it does not, writing an additional check before trying to open the file would be of little value.

    It's just added complexity and since it does not cover all eventualities, the file-not-found exception may still be thrown and need to be handled - probably in the same way as the 'file not found status code' would need to be.

  • I hate oracle (unregistered)

    This seems to be inspired by ODP.NET and the "error" message that reads: "Package state has been reloaded."

Leave a comment on “Not Exceptional”

Log In or post as a guest

Replying to comment #:

« Return to Article