7 ms·
Don’t Use Try/Catch (2010)
- vezzy-fnord 13y agoWhat the author really means under the provocative title is don't do error hiding, which is already well established as an anti-pattern.
- sherwin 13y agoI think the main point here is to avoid general catches and instead catch specific exceptions. The author raises the interesting point that if it's truly an exception, you're better off letting the system crash all together (especially in a webapp, where you're basically dropping a single request for a single user) -- and if it's an "expected exception", then you should be handling it directly. I don't see how that reduces to "never use try/catch" though, since catching a specific exception (or types of exceptions) is a way of "handling it directly."
- cleaver 13y agoUnfortunately, "Don't do X" is better click bait than "You should think carefully when you want to do X". There will be cases where you want to do "catch {}" — you don't always have control over the exceptions thrown by a lower-level library. It might be good to create a standard where you log them conditionally, or something that could aid in troubleshooting.
- joshribakoff 13y agoYes, in my front controller I wanted to log to the filesystem & email exceptions. The email library threw it's own exceptions, which I wanted to ignore with "catch {}"... if email was down, and I already logged the exception, there's nothing left to do.
- V-2 13y agoTrue, but as a developer, I expect a comment inside your empty catch block telling me why it is justified. I can't remember ever seeing one...
- JasonFruit 13y agoOddly, I have seldom seen an empty catch {} without a comment, though often it was simply to point out that, yes, this is intentional. Even that is better than leaving me wondering if the code is just unfinished.
- deathanatos 13y agoNot only are the points you raise valid, but I feel the webapp example exemplifies the strengths of exceptions: That the default behavior is to propagate to a context that can deal with the exception, and that you can catch them all at strategic points, like the main request handler of a webserver. You're not "crashing the thread" like the article implies: you're purposefully catching some error you didn't expect (bugs happen), logging/capturing it for debugging (perhaps even with a traceback), and gracefully returning at worst a 500 to the current request, all the while continuing to serve further requests. It's been best practice for quite some time not to catch { // heh heh he. }.
- joshribakoff 13y agoI absolutely agree. Magento does this & its one of the reasons why it sucks. They catch an exception, and throw a new one. Basically eating the message & stack trace. Then that one in turn gets caught and a 3rd new exception is thrown, eating it up again. By the time it bubbles up, your stack trace is totally useless.
- teddyh 13y agoPython 3.3 fixes this, by implementing PEP 415¹, which keeps the original exception available by using this syntax: except SomeException as exception: raise NewException("stuff happened") from exception 1) http://www.python.org/dev/peps/pep-0415/ http://www.python.org/dev/peps/pep-0415/
- jafaku 13y agoPHP added exception chaining in 5.3.0 (a few years ago). See $previous: http://www.php.net/manual/en/exception.construct.php http://www.php.net/manual/en/exception.construct.php
- Bahamut 13y agoFrom the frontend perspective, isn't it sometimes ideal to use try/catch? Unfortunately with the fragmented browser implementations of HTML5 and JavaScript, sometimes what is an exception in one browser is correct usage in another. It's a complex beast of a problem at times. Of course, you should be judicious in your usage of try/catch, since it's obviously something that can be abused very poorly.
- potatolicious 13y agoUnfortunately yeah - sometimes the brokenness of tr/catch you inherit from the platform level. Reminds me of when I was trying to write a Win8/Metro app for fun. Turns out in the particular network class I was using 404's throw exceptions. What a horrific design - 404 isn't an unexpected state at all, particularly when calling restful apis. But there we were, a pointless try/catch or nothing. A lot of the brokenness with exceptions is software that models expected operational state as exceptions.
- windowsworkstoo 13y agoYes that was an issue with the old WebRequest classes, but now with System.Net.Http the situation is much better (though they did what most people end up doing and wrapping WebRequest in a sensible manner)
- jakub_g 13y agoDue to asynchronous nature of JavaScript it's basically impossible to use "one big try/catch". Code that is invoked via setTimeout executes with an empty stack so something like try { setTimeout(foo, 1000) } catch (ex) { ... } won't be caught here if foo throws. In some DOM APIs there are 'onerror' handlers (like XHR), in NodeJS the convention is to have an "error" first parameter in the callback (which is null if there's no error). Also try-catch generates additional scope object inside the catch clause hence it's a bit more expensive than just doing a function call. Generally try-catch makes sense in JavaScript only locally when executing some external synchronous code that is known to throw exceptions.
- Aqueous 13y agoThe problem is sometimes you need to be able to report an exception elsewhere than the global log file , for example fold the exception into a user response. For a web application, for instance, using ANORM/Scala/Play, you might have a unique key constraint that throws an exception when it's violated. I need to be able to use that to emit a JSON response to the user telling them there is already a file with that name, extension combination etc. So I have to catch the exception in my controller in order to properly report that to the user. The author is right that your code needs to properly react to exceptions and not swallo them. . A global exception handler lets you report to all exceptions, but in order to give proper feedback to the user you definitely have to catch exceptions elsewhere in the code.
- V-2 13y agoI'd go one step further - throw your own exceptions whenever you can. Just put assertions in your code. Even verbose assertions. Which error report would you rather receive - "foo was set to null while file was still open!", or a generic "NullReferenceException" caught two stack frames away. If it crashes, it crashes anyway. After that it is only about how fast you can fix the bug.
- drdaeman 13y agoPlease, don't even think about such approach if you handle many long-living tasks (like, say, client connections) in a single OS-level unit of execution (process or thread) and the error/exception happens for a single task but crashes the whole stack.
- V-2 13y agoJust make sure they are caught and handled. Your single task should not allow any exceptions to bubble up all the way to the whole stack. Whether they are your own or not.
- MaulingMonkey 13y agoPlease use some restraint! Sometimes an exception is not the answer! I've had... I think it was Windows::UI::Input::PointerPoint::GetCurrentPoint throw exceptions if the finger passed in was no longer touching the screen. Sounds fine at first, right? Except... 1) This occurred before "finger released" events, so you'd run into a crash because they thought throwing an exception was better than returning the last known finger position, which would've rightly left me with no error report. 2) This occurred in a nasty rare corner case, making figuring out the reproduction a PITA. I don't think I'm alone in not expecting such a simple function to throw when given a known-to-me-valid fingerId. Worse, the exception was completely undocumented on MSDN -- either explicitly or as a hint from function signature (at least Win32 had the common decency to return BOOL or HRESULT.) 3) I found no method for validating a finger ID, so one had to simply catch the exception and accept the massive framerate dip of exception handling overhead if the user pawed at the screen. Before you mistake that for hyperbolic performance concerns: I could make a smooth 30fps tank to bellow 10fps consistently. I measured! Touch input isn't the only unexpected thing throwing exceptions for WinRT. The end result of this "throw exceptions whenever you can" mentality is I've been forced to build a habit of wrapping every WinRT API call in extremely wide try/catch blocks to log whatever random undocumented exceptions come crawling out of it. By becoming the rule, it took the "exception" out of "exceptions". I'm sure you'll agree: This is horrifically ugly, slow, and in generally poor taste. But it's necessary. The other alternative is you hopefully find as many as 90% of the weird junk that crashes your program with exceptions, most of which you don't actually care about in the slightest -- and the other 10% avoid discovery and instead explode your stuff in production, most of which will be for no good reason.
- Locke1689 13y agoOn Windows you may even want to let the application crash. If an application crashes on Windows due to an exception, it can be picked up by Microsoft's Watson error logging (now called Windows Error Reporting, I believe). If the user has marked the checkbox "help Microsoft improve Windows by sending crash information" then the dump of the application will be sent to a central location, where it can be triaged and accessed by the application's developer. Now instead of just a generic entry in a log file, you have a full memory dump of the exception.
- evadne 13y agohttp://en.wikipedia.org/wiki/Windows_Error_Reporting#Third-party_software http://en.wikipedia.org/wiki/Windows_Error_Reporting#Third-p...
- gweinberg 13y agoI used to use try/catch with an empty catch block in Java all the time. The exception could never in fact occur, but the compiler required me to either add a catch block or declare that my function raises an exception, when it fact it doesn't. Yes, I did include a "this never happens" comment. That is my favorite comment, but only if it is true.
- wheaties 13y agoAh, it was people like you who did this even when, as you said it should never happen, that caused me many a late night... 'cause it did and that empty catch block hid it. Don't leave empty catch blocks. At least put in some form of logging of the exception, just in case.
- Mindless2112 13y agoThe most common code I write in C# is in switches on enums: default: throw new InvalidOperationException("Should never happen!");
- alecdbrooks 13y agoMy thought would be to add an assertion that always fails inside the catch block, but this probably only makes sense if you use assertions already, as they have to be turned on explicitly in Java.
- buerkle 13y agoYears ago I found the source of my troubles which took longer than it should have because Tomcat had an empty catch around InterruptedException with a "this will never happen" comment.
- gst 13y agoWhy don't you just throw a runtime exception inside the catch block?
- beambot 13y agoJoel Spolsky's thoughts on exceptions (ie. "They're no better than gotos") shares a similar perspective: http://www.joelonsoftware.com/items/2003/10/13.html http://www.joelonsoftware.com/items/2003/10/13.html
- alexRohde 13y agoI cannot believe this got on the front page. Structured exception handling is crucial for atomicity and building robust systems. Nothing about catch requires the program to continue executing as though no exception ever happened, many catches can be fatal but handle emergency cleanup.
- angersock 13y agoHow do you feel about Erlang?
- dsego 13y agoThe title is misleading. The gist of the article is in the last sentence: "A system that swallows and masks exceptions isn’t a healthy system."
- tbarbugli 13y agoDont give crappy titles!
- pan69 13y agoI flagged this because of the link-bait title.
- __derek__ 13y agoOr use exceptions to write cleaner code: http://www.jeffknupp.com/blog/2013/02/06/write-cleaner-python-use-exceptions/ http://www.jeffknupp.com/blog/2013/02/06/write-cleaner-pytho.... That post is specific to Python, which actually implements a lot of internal features using try-except, but it suffices as an argument against the idea that catching exceptions is itself a bad practice.