- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Frist of all Russell should have used a capable debugger which can trap an exception.
Admin
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
Admin
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.
Admin
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.
Admin
"If we don't test for Covid^H^H^Hbugs there we won't be any bugs".
Admin
AKA "Pokémon exception handling"- for when you "gotta catch them all"!
Admin
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.
Admin
Admin
*led
Admin
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.
Admin
At least they understood that the comment doesn't need to be copied to achieve the same functionality. If only they understood the comment...
Admin
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.
Admin
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.
Admin
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.
Admin
"Cargo cult" programming at its finest. I don't know what it does, but the guru did it, so it must be good.
Admin
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.
Admin
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?
Admin
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.
Admin
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.
Admin
Adding things to a company style is always easier than removing them, or making them optional.
Admin
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.)
Admin
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.
Admin
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)".
Admin
Can someone sanity-check this? At least in Java, the stack trace is built when the
Throwable
is constructed, not when it'sthrow
n, so rethrow
ing 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.Admin
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.
Admin
Talk about cargo-cult programming!
Admin
@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.
versus
There's a reason for each, but certainly the first is the more common.
Admin
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).
Admin
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.
Admin
BTW, I'm 100% right. I claimed that my predecessors used the second form, and it resets the stack trace.
Admin
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.
Admin
@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.
Admin
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.
Admin
hah, i usually do
bool noop = true;
Admin
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).
Admin
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:
Admin
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.
Admin
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.