• Anonymous (unregistered)

    Frist of all Russell should have used a capable debugger which can trap an exception.

  • MIKE (unregistered)

    I think that there is the antipattern of exception swallowing. Now, it could be ok only in few cases, when you know that an exception isn't a problem

  • Martin (unregistered)

    If it was only pointless but otherwise not causing harm one could just shrug and ignore it. But it is silently swallowing exceptions. So you end up with undefined system state when that happens and have no chance of knowing it. I once had a coworker who thought that a good idea... called it defensive programming.

  • (author) in reply to Martin

    In the Visual Basic days, we had "On Error Resume Next", which was how you told a VB program to just set an error code variable but continue execution on any errors. There were more than a few times I saw someone describe that as "crash proofing" your program.

  • Dave (unregistered) in reply to Remy Porter

    In the Visual Basic days, we had "On Error Resume Next"

    "If we don't test for Covid^H^H^Hbugs there we won't be any bugs".

  • Vilx- (unregistered)

    AKA "Pokémon exception handling"- for when you "gotta catch them all"!

  • Matthew (unregistered) in reply to Anonymous

    I've done that before, recently. The ASP.net page was eating exceptions (for logging) and I couldn't be bothered to alter VS to capture it explicitly.

  • I'm not a robot (unregistered) in reply to Remy Porter
    There were more than a few times I saw someone describe that as "crash proofing" your program.
    As in "proof that the program will crash"?
  • (nodebb)

    This lead to some conflict

    *led

  • Foo AKA Fooo (unregistered) in reply to Martin

    Not necessarily undefined. As MIKE said, it can be ok to swallow an exception, but typically only in a few cases, e.g. what I like to call "plan B exceptions", i.e. try a fast or easy method first, and if it fails, try the slower but more general way; or when loading an optional resource, swallow a file-not-found exception (but not just any exception -- a read error on an optional resource doesn't mean the resource isn't there, but there's a real problem with it which should be reported).

    As for Russel, if he's got any authority at all (and it sounds like he does), I don't see why he couldn't just announce in a meeting: "I once made a mistake by committing that "ex = ex;" line. I'm sorry about that. It's really pointless. You don't need to write it, and you can remove it when you see one (but no sweat)." For a good leader, there's nothing better than a sincere but inconsequential apology. It "proves" to their underlings that they're not a dictator and not above admitting mistakes, while not giving anyone a real attack surface (as in, "remember what a stupid mistake our boss made"). At best, "ex = ex" becomes a running gag that the leader can even chime in on.

  • Anonymous (unregistered)

    At least they understood that the comment doesn't need to be copied to achieve the same functionality. If only they understood the comment...

  • Naomi (unregistered)

    it can be ok to swallow an exception, but typically only in a few cases, e.g. what I like to call "plan B exceptions", i.e. try a fast or easy method first, and if it fails, try the slower but more general way

    I don't think that's swallowing the exception at all. It sounds more like you handled it! Y'know, in your exception handler. :P

    I'm being playful here, but I do feel like the idea that all exceptions must be logged is way too prevalent, and really missing the point.

  • Foo AKA Fooo (unregistered) in reply to Naomi

    I meant swallowing the exception object (because I don't care for the particular exception).

    You could say I handled it (although I ignored it :), though not necessarily in the EH, could also be in the code after it something like (I won't even bother with formatting here):

    try { plan_a (); return; } catch (exception) { } plan_b ();

    Especially if plan_a is only possible in some cases anyway, so there'd be an "if" before the "try".

    And I fully agree with your last sentence. I'd even say, either handle it (meaningfully), or report it, in most cases.

  • Functional (unregistered)

    I prefer running effects, and thus handling errors, in only one location of the entire program. prepare, or make, or setup. Take that output, and run, or execute, or install. throw means the program needs to restart.

  • Bill T (unregistered)

    "Cargo cult" programming at its finest. I don't know what it does, but the guru did it, so it must be good.

  • Simon Clarkstone (unregistered) in reply to Foo AKA Fooo
    try { plan_a (); return; } catch (exception) { } plan_b ();
    

    That can work, but in some cases will have the risk of failing silently. For example, if later changes to the program cause code deep inside plan_a() to encounter some configuration data isn't initialised and it always throws a NullPointerException, then possibly no-one will notice that it is failing.

    • Unit tests might not detect that because you won't test every combination of things being pointlessly null nor check deep inside all the fields that are passed in.
    • Larger-scale tests aren't likely to detect it because plan_b() will recover the situation and such a test won't look at any details that record whether plan_a() or plan_b() was taken.
  • hartmut holzgraefe (google)

    Probably not even going to work as any somewhat decent compiler these days would optimize that line away, so a breakpoint can either not be set on it, or never gets triggered, unless doing a totally unoptimized build for debugging purposes?

  • Alex (unregistered) in reply to Remy Porter

    Stop it, you're giving me 'Nam flashbacks...

    Annoyingly, in VBA, a lot of rather basic functionality is only accessible by triggering an error. For example, the only way I've found to determine the dimensionality of an array is to write a loop that repeatedly calls UBound(<array>, <dimension>) and see at what point it stops working. So Pokemon error-trapping is pretty much a best practice.

    I've got into the habit of indenting any code that falls between "On Error Resume Next" and the subsequent "On Error GoTo 0", as a sort of pseudo-block statement. Doing it inline makes my skin crawl.

  • sizer99 (google) in reply to hartmut holzgraefe

    We deploy debug builds of C# stuff internally because it's fast enough as it is, and then we can always attach a debugger in flight (the tiny amount of stuff that's really time critical is C++ DLL). So if you're running like that your exceptions would still be there.

    Of course the better way to handle THIS is to have a top level exception handler that will catch any exception and log the full stack dump instead of just having the program crash. You can also check when you're running in VS and not do that.

  • Your Mammas name (unregistered)

    Adding things to a company style is always easier than removing them, or making them optional.

  • Foo AKA Fooo (unregistered) in reply to Simon Clarkstone

    a) I wasn't specific on what type of exception to catch (that depends on the language etc.), but logical errors, which include NullPointerException, should normally not be handled at all (just logged), including here. But your argument would hold e.g. if something called by plan_a wants to read a file which was now removed. So:

    b) There should be at least one unit test that specifically tests that some particular case is handled by plan_a. That's a special case of code coverage (here, coverage of the "return" statement after plan_a). Usually, there would be several of those, to test the various paths in plan_a. (This might entail adding a special flag "handled_by_plan_a" just for testing, but that's really an implementation detail.)

  • Prime Mover (unregistered) in reply to Foo AKA Fooo

    Any program that fails to trap every null pointer exception that it encounters is a faulty program. You may not necessarily know what to do with it, and you may find it is appropriate to "just" log it and run the exit-gracefully procedure, but if you find there are conditions under which certain modes of user error cause it to crash with a NPE stackdump, go away and finish the damn thing.

  • (nodebb)

    This pattern is common in the code I inherited:

    try { dostuff(); } catch (exception ex) { throw ex; }

    I really can't fathom how this started. It manages to be worse than no exception handler at all. For those that don't know C#, this pattern boils down to "when there is an exception, don't do anything except obliterate the most interesting part of the call stack, and sometimes parts of the actual problem (e.g. InnerException)".

  • Naomi (unregistered) in reply to Jaime

    when there is an exception, don't do anything except obliterate the most interesting part of the call stack, and sometimes parts of the actual problem (e.g. InnerException)

    Can someone sanity-check this? At least in Java, the stack trace is built when the Throwable is constructed, not when it's thrown, so rethrowing won't ever wipe away anything. It's such a common operation that I have a difficult time believing even Microsoft would bungle it that badly.

  • ooOOooGa (unregistered) in reply to Naomi

    That's my assumption also. As Jaime originally wrote it, it should just be throwing the same exception. On the other hand, the similar code:

    try { doStuff(); } catch (Exception ex) { throw new Exception(); }

    Is all sorts of terrible. Especially if catching a specific exception type and throwing a generic Exception type.

  • (nodebb)

    Talk about cargo-cult programming!

  • WTFGuy (unregistered) in reply to Naomi

    @naomi

    Nope. Jaime is right. Or at least half-right. There are two ways to code this. One restarts the stack trace from the rethrow point, one does not.

    try {
      doStuff() ;
    }
    catch (Exception ex)  {
        // rethrow exception with complete accumulated call stack, all inner exception(s), etc.
        throw   
    }
    

    versus

    try {
      doStuff() ;
    }
    catch (Exception ex)  {
        // rethrow exception with this call site as the leaf  node of the callstack and losing inner exception(s) under some circumstances.
        throw  ex 
    }
    

    There's a reason for each, but certainly the first is the more common.

  • Foo AKA Fooo (unregistered) in reply to Prime Mover

    Exactly, catch and log and exit gracefully, to ultimately fix the cause of the NPE. But that's typically done at a rather high level, not in a place like this.

    But you cannot meaningfully handle a logical error (which includes most cases of NPE), because they indicate a bug, i.e. a mistake in your reasoning about the program, so by definition you don't know what to do about it until you understand the situation (and hopefully fix the bug).

  • Old timer (unregistered) in reply to Remy Porter

    In 'c' days, 'On Error Resume Next' was the only form of error handling available -- there was no exception creating and handling meta program. In BASIC, it was the way to write code that you REALLY REALLY didn't want to create exceptions, but the language and environment threw exceptions anyway. Particularly and specifically, external input -- text, user, or serial port. Where exceptions aren't exceptional, where 'errors' are expected, where you want your local code to handle the expected 'errors', not to throw exceptions taking you out of program sequence.

  • (nodebb) in reply to WTFGuy

    Jaime is right. Or at least half-right.

    BTW, I'm 100% right. I claimed that my predecessors used the second form, and it resets the stack trace.

  • Clem Fandango (unregistered)

    Years ago I started a job in a small company as a Delphi developer. Delphi doesn't have garbage collection, but I noticed that every single developer there was writing code where an object, once it was no longer required, was first set to null and then freed. Oddly enough Delphi didn't throw exceptions on attempting to free a pointer that was set to null. But this pattern was throughout the codebase, slavishly followed for years by all the 30-odd developers who worked there.

    Somehow it had never occurred to them to try and find out why they had so many memory leaks in their application.

  • WTFGuy (unregistered)

    @Jaime: Sorry if you took offense.

    What I really meant was you told half the story of the language feature. That half was what surprised Naomi.

  • Foxglove (unregistered) in reply to Alex

    I think one of the reasons VBA has such a bad reputation among programmers is that they don't really understand what being integrated with Office means: stuff like this isn't in VBA on its own, it's in VBA+Office.

    If you want to know how many dimensions an array has, write one row of it to a spreadsheet and check how many columns it uses. (AFAIR - it's been a long time.)

    That's completely batshit if you're not used to it, but makes sense in context. VBA is a tool for automating Office rather than a full programming language. Whatever you're doing in VBA can be expressed in terms of clicks and keystrokes within Excel (or other Office applications) - but that's the wrong way around, because really VBA is a tool for automating the clicks and keystrokes, so you start with those and then turn them into code.

    You can't write good VBA code unless you're both a good programmer and an expert user of the Office programme(s) you're working with.

  • sh_code (unregistered)

    hah, i usually do

    bool noop = true;

  • (nodebb) in reply to WTFGuy

    What really surprised me was that they used the longer form. Doing it right is actually easier than doing it wrong. They didn't even have the excuse of being former Java programmers.

    Even worse... they supported this application for at least five years and must have been frustrated by the incomplete stacks in the logs (those were being saved).

  • (nodebb) in reply to Foxglove

    I think one of the reasons VBA has such a bad reputation among programmers is that they don't really understand what being integrated with Office means

    I don't think this is true. Stand-alone VB has exactly the same reputation, and it has no ties with Office at all. VB's big problems are:

    1. It's so old that its primary design driver has long been backwards compatibility. That means that it only gets modernized if doing so doesn't break code.
    2. Its simple to read syntax and ubiquitousness mean that there is a lot of bad VB code in the world, and a lot of bad programmers have been successful using it. "Getting help" with VB often means that the asker gets really bad advice.
    3. It doesn't play well with build systems, source code control, or modern development workflows. This keeps the professionals away.
  • (nodebb)

    Yeah, I can confirm pre-.NET VB is just as awful as VBA. There are so many terrible things in that language. I found that passing a zero-length array to a function and then looping over all array items can work "as expected" in debug mode - i.e. the inner loop body will execute 0 times - but when compiled in release mode it will throw an exception because you can't actually get the bounds of a zero-length array.

    Another example - any sensible language would choose either zero-based array indices or one-based indices. VB uses both, depending on what kind of array or collection you have, and then gives the user the ability to define their own start and end indices for arrays.

  • Craig (unregistered)

    Pre-.NET VB the language is VBA. The standalone product added a forms engine and ahead-of-time native compiler (I believe using a customized version of the C and C++ back-end). The programming language part is identical. The "Option Base" parts are crazy, but defining start and end is eminently sensible (Fortran also does it). The biggest WTF of .NET VB is how badly they bungled arrays.

Leave a comment on “An Exceptional Leader”

Log In or post as a guest

Replying to comment #516126:

« Return to Article