• (cs)

    People are too quick to just catch a generic Exception. Derp.

  • (cs)

    I like the way the code formatter carefully highlights the identifier "function" as if it is a keyword...

  • ben (unregistered)

    I dont understand where the recursion is and what the problem is: getPersonsInformation and lookup.getPersonsInformation can surely be different methods.

  • 30into (unregistered)

    public static bool Comment(){ try { return PostCommentFrist(); } catch (Exeption e) { return Comment(); } }

  • MightyM (unregistered) in reply to ben
    ben:
    I dont understand where the recursion is and what the problem is: getPersonsInformation and lookup.getPersonsInformation can surely be different methods.

    The recursion is in the catch-block where the method calls itself with the original parameters.

  • Dave (unregistered) in reply to ben
    ben:
    I dont understand where the recursion is and what the problem is: getPersonsInformation and lookup.getPersonsInformation can surely be different methods.

    The recursion is in the catch part of the exception handler. It calls itself with the attributes it was passed.

  • (cs)

    Do or do not. There is no try.

    (I guess Yoda wasn't a programmer)

  • ben (unregistered)

    The recursion is in the catch-block where the method calls itself with the original parameters.

    Thanks. Looked in the wrong spot. So there will only be a recursion if the desired Service was not available. Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.

  • ¯\(°_o)/¯ I DUNNO LOL (unregistered)

    If the compiler is smart enough, it can see that this is a case of tail recursion and avoid stack overflow. That still doesn't mean that this code isn't retarded as fuck.

  • Mike5 (unregistered) in reply to ¯\(°_o)/¯ I DUNNO LOL
    ¯\(°_o)/¯ I DUNNO LOL:
    If the compiler is smart enough, it can see that this is a case of tail recursion and avoid stack overflow. That still doesn't mean that this code isn't retarded as fuck.

    We are talking about Java compiler here. It won't even filter out needless assignments, and you expect it to notice tail recursion?

  • (cs) in reply to ben
    ben:
    So there will only be a recursion if the desired Service was not available. Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.
    There will be infinite recursion when there is any error. Some access methods will throw an exception when a record cannot be found. Or is null. Or whatever. Adding sleep() is only going to delay the inevitable.

    But suppose you add a 1 second sleep. While the default stack may not be very deep, it certainly allows hundreds to thousands of simple calls. Then it could take an hour to exhaust the stack. And still end in a rather uninformative "stack overflow" exception.

    No, this method is quite exceptional. I hope.

  • (cs) in reply to Mike5
    Mike5:
    We are talking about Java compiler here. It won't even filter out needless assignments, and you expect it to notice tail recursion?
    The JIT isn't as braindead as javac.
  • faoileag (unregistered)

    "There will one day be lemon-soaked paper napkins. Till then there will be a short delay. Please return to your seat."

  • Julia (unregistered)

    Would be more amusing if lookup.getPersonsInformation() did a lookup on an external paid-for data service, in which case a stack overflow is the least of their worries. BailiffsComingToCollectOnLargeDebtException perhaps?

  • faoileag (unregistered) in reply to ben
    ben:
    So there will only be a recursion if the desired Service was not available.
    How do you know?

    lookup.getPersonsInformation(loginInfo, department, function) might throw an exception on its own right if:

    • the login credentials are wrong
    • the department does not exist
    • the function does not exist for the given department
    • the function is currently vacant

    And then you have to accomodate all the exceptions that might be thrown by code that lookup.getPersonsInformation() uses and does not deal with itself.

  • (cs) in reply to faoileag
    faoileag:
    "There will one day be lemon-soaked paper napkins. Till then there will be a short delay. Please return to your seat."

    +1 HHG

  • Mike (unregistered)

    Looks like the kind of stuff I see around here. Of course we have more than enough of the empty catch (swallowing any exception and continuing as if nothing happened).

    It's amazingly hard to convince people that "they're doing it wrong..."

  • ANON (unregistered)

    And about half a year ago you laughed at me, when I said that an empty catch block is not the worst. Now you have it.

  • ACSI (unregistered)

    Work harder, meatbots! Stack deeper!

  • Metric (unregistered) in reply to Mike
    Mike:
    It's amazingly hard to convince people that "they're doing it wrong..."
    Did they tell you you should grow up When you wanted to dream Did they warn you, better shape up If you want to succeed I don't know about you Who are they talking to They're not talking to me

    I'm higher than high Lower than deep I'm doing it wrong Singing along

  • Tux "Tuxedo" Penguin (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    I like the way the code formatter carefully highlights the identifier "function" as if it is a keyword...

    Code formatter just think it's a C-Pascal. It is rare dialect of Pascal that has c-style declaration (type first, identifier last) and ability to define identifiers anywhere in code (no var or const block, though type block is still there), but otherwise it has still Pascal syntax where function is still a keyword (functions and procedures are declared same way as in pascal). Though frankly it seems more like C-Pascal++ as it has classes.

  • (cs) in reply to ochrist
    ochrist:
    Do or do not. There is no try. (I guess Yoda wasn't a programmer)
    He could have been; he just used VB6 error handling:
    Public Function DoIt As Boolean
        On Error Goto Exit_Function
        ...
        DoIt = True
        Exit Function
    

    Exit_Function: DoIt = False Exit Function

    This way, it works, or it does not, and you can find out which.

  • anonymous (unregistered) in reply to Mike

    Sometimes it is really reasonable to just ignore the exception, I did write code that have empty catch block...

    To put simply, I need to loop URL that formatted something like http://www.example.com/XXX (XXX=000-999), but some URL simply didn't exist and I don't care. However the library would throw HTTP exception on 404 not found error. Of course I would write an empty catch block...

  • (cs) in reply to ben
    ben:
    Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.
    Leave NOW. Please turn in your programming license at the door.

    The sleep() might allow you to avoid some causes of the exception (e.g. throw new TemporaryFailureException("Please try again in 500ms") (*)), but others (especially things like NotAuthorisedException("I HATE YOU")) will be permanent, so as mentioned above you will merely overflow the stack more slowly.

    (*) Yes, a "try again in 500ms" error should just wait 500ms and try again itself. It's just a stupid example, so sue me, OK.

  • (cs)

    Now I got a song going through my head, based on the chorus of Kenny Roger's "The Gambler":

    You've got know when to try 'em. Know when to throw 'em. Know when to catch 'em all. Know when to run.
    Hmm, makes me think of how to represent the next line.
    You never count your money while you're sitting at the table.
    Maybe as a SQL error: COUNT() is not valid on field type Currency during Table.sitting operation.
  • JM (unregistered)

    The throws declaration in the method signature for an exception that can't be thrown due to the catch is a nice touch.

  • Rupee Everet (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    ben:
    Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.
    Leave NOW. Please turn in your programming license at the door.

    The sleep() might allow you to avoid some causes of the exception (e.g. throw new TemporaryFailureException("Please try again in 500ms") (*)), but others (especially things like NotAuthorisedException("I HATE YOU")) will be permanent, so as mentioned above you will merely overflow the stack more slowly.

    (*) Yes, a "try again in 500ms" error should just wait 500ms and try again itself. It's just a stupid example, so sue me, OK.

    So you're advising him to:

    (a) reduce the wait time by half. (b) move the recursion up a level so that you are adding an additional call to the stack with each retry.

    ... meaning, you will fill out the call stack twice as fast!

    Nice going genius.

  • Mat (unregistered)

    If at first you don't succeed, try try again?

  • Walky_one (unregistered) in reply to anonymous
    anonymous:
    Sometimes it is really reasonable to just ignore the exception, I did write code that have empty catch block...

    To put simply, I need to loop URL that formatted something like http://www.example.com/XXX (XXX=000-999), but some URL simply didn't exist and I don't care. However the library would throw HTTP exception on 404 not found error. Of course I would write an empty catch block...

    Ignoring One exception might be OK. But need to ensure that you don't catch exceptions of other problems

    1. Only catch specific exceptions
    2. Ensure that this exception is only raised on the case you want to ignore.
    3. DOCUMENT IT! (there never is an empty catch block. At least you need something like "Ignore exception because <insert reason>".

    As you can see, the culprit today will catch any exception and try again (even if it's "Out Of Memory").

  • (cs) in reply to Rupee Everet
    Rupee Everet:
    Steve The Cynic:
    ben:
    Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.
    Leave NOW. Please turn in your programming license at the door.

    The sleep() might allow you to avoid some causes of the exception (e.g. throw new TemporaryFailureException("Please try again in 500ms") (*)), but others (especially things like NotAuthorisedException("I HATE YOU")) will be permanent, so as mentioned above you will merely overflow the stack more slowly.

    (*) Yes, a "try again in 500ms" error should just wait 500ms and try again itself. It's just a stupid example, so sue me, OK.

    So you're advising him to:

    (a) reduce the wait time by half. (b) move the recursion up a level so that you are adding an additional call to the stack with each retry.

    ... meaning, you will fill out the call stack twice as fast!

    Nice going genius.

    Bad reading, on your part. He didn't specify a waiting period. No-one suggested an extra function call. And who cares if he fills up the stack twice as fast if it's going to fill up anyway.

  • Smug Unix User (unregistered)

    I know he needed a global to store a number of tries. That way he only recurses a limited number of times.

    If(_numberOfTries < MAX_NUMBER_OF_TRIES) then
       sleep(_numberOfTries * 1000)
       getPersonsInformation(person, department)
    Else
       throw New Exception("Something doesn't work") 'Must hide original exception
    

    /sarcasm

  • (cs) in reply to Mike5
    Mike5:
    We are talking about Java compiler here. It won't even filter out needless assignments, and you expect it to notice tail recursion?
    The problem with filtering out tail recursion is that it's possible to see the result of that happening in some circumstances (notably in a stack trace, which Java allows you to obtain). So javac doesn't. The JIT might do the optimisation, if it can prove that the result isn't practically observable.

    But Java programmers tend to not write deeply recursive code anyway. They're like C and C++ in that. If they wanted to write recursive stuff all over the place, they'd use Scala or Clojure (where the initial compiler is allowed and expected to do much more extensive optimisations)…

  • Moo Cow (unregistered) in reply to Tux "Tuxedo" Penguin
    Tux "Tuxedo" Penguin:
    Steve The Cynic:
    I like the way the code formatter carefully highlights the identifier "function" as if it is a keyword...

    Code formatter just think it's a C-Pascal. It is rare dialect of Pascal that has c-style declaration (type first, identifier last) and ability to define identifiers anywhere in code (no var or const block, though type block is still there), but otherwise it has still Pascal syntax where function is still a keyword (functions and procedures are declared same way as in pascal). Though frankly it seems more like C-Pascal++ as it has classes.

    I would have gone with "the formatter thinks it's JavaScript", but your guess seems equally valid.

  • faoileag (unregistered) in reply to Smug Unix User
    Smug Unix User:
       sleep(_numberOfTries * 1000)
    
    There is room for improvement:
       sleep(fibonacciNumber(_numberOfTries) * 1000)
    
    I recall having once read that the fibonacci sequence is a good base for allocating resources, so it might come in handy here as well.
  • NotRegisteredYet (unregistered)

    Could

    getPersonsInformation(loginInfo, department, function)

    be more specific and more likely to fail than

    getPersonsInformation(department,function)

    maybe the second causes some default values to be used and so is safe to run?

  • EvilSnack (unregistered)

    Putting on my asbestos suit... Okay.

    TRWTF is exceptions, period. I have yet to encounter a situation where exception processing delivers the same level of quality, for the work involved, as a regimen of simply returning an error and then checking the return for errors.

    It's true that exceptions provide the flexibility of dealing with errors somewhere other than at the point of the function call, but I have not yet seen a situation where the error was better handled elsewhere. Maybe there is, but in my experience there isn't.

  • (cs) in reply to Dogsworth
    Dogsworth:
    People are too quick to just catch a generic Exception. Derp.
    They obviously think exceptions are like Pokémon.
  • faoileag (unregistered) in reply to NotRegisteredYet
    NotRegisteredYet:
    Could

    getPersonsInformation(loginInfo, department, function)

    be more specific and more likely to fail than

    getPersonsInformation(department,function)

    maybe the second causes some default values to be used and so is safe to run?

    They are completely different methods that don't have anything to do with each other apart from the fact that getPersonsInformation(department,function) calls lookup.getPersonsInformation(loginInfo, department, function).

    Actually, we do not even know if ServiceLocator is a class provided by a third party or if its code is under the auspices of the coder who wrote the getPersonsInformation(department,function) wrapper around it.

  • nmclean (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    ben:
    Adding a sleep() at the beginning of the catch-clause and this code is a little less wtf.
    Leave NOW. Please turn in your programming license at the door.

    The sleep() might allow you to avoid some causes of the exception (e.g. throw new TemporaryFailureException("Please try again in 500ms") (*)), but others (especially things like NotAuthorisedException("I HATE YOU")) will be permanent, so as mentioned above you will merely overflow the stack more slowly.

    (*) Yes, a "try again in 500ms" error should just wait 500ms and try again itself. It's just a stupid example, so sue me, OK.

    You do realize that ben said it would make it "a little less wtf", yes? Are you disagreeing with this? Are you saying that code that recursively cycles constantly based on a catch-all exception is BETTER than code that cycles with a delay based on a catch-all exception? If so, please turn in your programming license at the door.

    Obviously the implementation is poor, but the comments saying that infinite recursion is an absolute ("the only reason this won’t run forever...", "...when there is any error") are premature. Without knowing what lookup.getPersonsInformation does (or getLookupLocal, for that matter), we can't say that. In some (most?) cases, the problem may not be permanent. Adding a sleep would:

    • lower CPU load
    • increase the likelihood that a call will succeed before the stack is exhausted

    It doesn't fix the code, but it certainly does make it slightly more sane.

  • (cs) in reply to JM

    I wonder if there was originally a re-throw in the catch block.

  • faoileag (unregistered) in reply to EvilSnack
    EvilSnack:
    TRWTF is exceptions, period. I have yet to encounter a situation where exception processing delivers the same level of quality, for the work involved, as a regimen of simply returning an error and then checking the return for errors.
    Assuming that in Java you can catch exceptions by their interface, two points come to mind:
    1. With exceptions you can far more easily deal with "families" of errors. With error codes you have to evaluate every single error code and determine what to do with it. With exceptions, this is far easier because you can group them by Interfaces, e.g. ICredentialException, INetworkException etc.

    2. If future versions of your code introduce new error conditions, with error codes you will most likely have to update your error handling (unless you just have generic error handling, "if res < 0..."). With exceptions things are a lot easier - as long as you catch by interface, it doesn't matter if the a new version introduces a new exception.

    Of course, you could emulate that with returning error objects instead of error codes, but I haven't seen that anywhere yet.

  • (cs)

    Okay, let's count other WTFs:

    • Non-generic Collection
    • Catching Exception instead of a subclass
    • Using a temporary variable where returning from the try block itself would have sufficed
  • NotRegisteredYet (unregistered) in reply to faoileag

    Yep, I didn't read the name of the collection

  • Evan (unregistered) in reply to ¯\(°_o)/¯ I DUNNO LOL
    pjt33:
    Mike5:
    We are talking about Java compiler here. It won't even filter out needless assignments, and you expect it to notice tail recursion?
    The JIT isn't as braindead as javac.
    The JIT doesn't do it either; the JVM model doesn't make it easy, because a full and correct stack trace has to be available.
  • QJo (unregistered) in reply to anonymous
    anonymous:
    Sometimes it is really reasonable to just ignore the exception, I did write code that have empty catch block...

    To put simply, I need to loop URL that formatted something like http://www.example.com/XXX (XXX=000-999), but some URL simply didn't exist and I don't care. However the library would throw HTTP exception on 404 not found error. Of course I would write an empty catch block...

    Well that's as maybe. but what you do not do here is:

    } catch (Exception e) {
    }
    

    What you're supposed to do is:

    } catch (UnknownURLException uue) {
    } catch (OtherSortsOfException e) {
       ... do something appropriate
    }
    

    Just catching and swallowing every exception when you're only interested in the one is abysmal practice.

  • anonymous (unregistered)

    If the lookup.getPersonsInformation function randomly throws an error instead of returning the correct (existing) result, then it is TRWTF. Still, the "better" way to do this would be to iterate a finite number of times and silently log the exceptions, then stick in a last-ditch attempt without any catch so that instead of throwing a nondescript stack overflow error you'll get the error that the function actually threw.

  • EvilSnack (unregistered) in reply to faoileag
    faoileag:
    EvilSnack:
    TRWTF is exceptions, period. I have yet to encounter a situation where exception processing delivers the same level of quality, for the work involved, as a regimen of simply returning an error and then checking the return for errors.
    Assuming that in Java you can catch exceptions by their interface, two points come to mind:
    1. With exceptions you can far more easily deal with "families" of errors. With error codes you have to evaluate every single error code and determine what to do with it. With exceptions, this is far easier because you can group them by Interfaces, e.g. ICredentialException, INetworkException etc.

    2. If future versions of your code introduce new error conditions, with error codes you will most likely have to update your error handling (unless you just have generic error handling, "if res < 0..."). With exceptions things are a lot easier - as long as you catch by interface, it doesn't matter if the a new version introduces a new exception.

    Of course, you could emulate that with returning error objects instead of error codes, but I haven't seen that anywhere yet.

    We do use error objects.

    In most of our applications, the type of error is only of interest to the developer, so any error return is as bad as any other, and so checking for the non-error return is good enough in most applications.

    As for future versions returning new error codes, if we already check for the non-error return, the new error codes are still only interesting to the developer.

    The only time the specific error is important to the user is if there is something the user can do to make another attempt successful.

  • QJo (unregistered)

    I wonder whether this is just a pre-coffee blunder that didn't get noticed on code delivery.

    I have on a plurality of occasions written code with the following execrable pattern:

    private String attr;
    :
    :
    public String getAttr () {
        return this.getAttr();
    }
    

    when I really meant to type:

    private String attr;
    :
    :
    public String getAttr () {
        return this.attr;
    }
    

    The difference between the blooper above and the OP is the fact that the above is instantly obvious the first time it is run. The OP may never get tested if the method serving it is sufficiently reliable and has never thrown an exception during its lifecycle.

    The real WTF of course is that unit testing didn't catch it.

  • (cs)

    Well of course it's a WTF. He should have written it with a loop:

    Collection persons = null;
    while (true)
    {
       try {
          persons = lookup.getPersonsInformation(loginInfo, department, function);
          break;
       } catch(Exception e) {
          //try, try again
       }
    }
    return persons;
    

    Recursion isn't the solution for everything!

  • Valued Service (unregistered) in reply to Mat
    Mat:
    If at first you don't succeed, try try again?

    If at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, try if at first you don't succeed, BRAIN SEIZURE no more memory left to remember what I was doing!!!

Leave a comment on “Exceptional Recursion”

Log In or post as a guest

Replying to comment #:

« Return to Article