TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Exceptions (2003)

63 pointsby ablover 11 years ago

22 comments

beagle3over 11 years ago
Everyone here seems to agree that &quot;exceptions are for exceptional conditions&quot;. The problem is that when you get down to details, there is disagreement about what exactly is an &quot;exceptional condition&quot;.<p>e.g. - you are trying to open a file for reading. The file does not exist. Is this exceptional? That depends on context, but the function that opens the file, being in an independent library, is usually designed without this context.<p>If it does throw an exception, some people complain that &quot;of course it&#x27;e expected that file won&#x27;t be there sometimes! that&#x27;s not exceptional&quot;.<p>If it doesn&#x27;t throw an exception, some people complain that &quot;we tried to open a file, but didn&#x27;t succeed, of course that&#x27;s an exception&quot;. But if you want to avoid an exception in this case, you&#x27;ll need to check for existence before opening (LBYL &quot;look-before-you-leap&quot;), and get into a race condition (TOCTOU &quot;time-of-check,time-of-use&quot;), which is really bad.<p>So it very often happens that you are forced by your ecosystem to use exceptions for normal control flow. Claims that you can only use it for &quot;exceptional &#x2F; unexpected&quot; tend to be incompatible with a project in which you do not develop&#x2F;control all of the library you use to your strict standard of exceptionalness.
评论 #6311144 未加载
评论 #6311107 未加载
评论 #6311129 未加载
评论 #6311093 未加载
评论 #6313223 未加载
评论 #6311086 未加载
betterunixover 11 years ago
I think Common Lisp has a good approach with its restarts system. I try to write something to a file but there is not a enough disk space? How about telling the user, then invoking a restart when the user says, &quot;There is more space available!&quot; and continuing execution as if nothing went wrong? The problem with exceptions is that there is no way to recover from them in most languages, because the exception handler is found by unwinding the stack.<p>What I do not like about the &quot;check return values&quot; approach is:<p>1. It means that client code must understand how to handle error conditions. No disk space? Well whoever called the top-level function that invoked <i>write</i> needs to figure out what to do if there is any chance of recovery. It is a maintenance headache that can quickly accumulate bugs.<p>2. In both Java and C++ there are functions that cannot return values: constructors, and in C++ destructors. No, it is not acceptable for a program to crash just because a constructor call failed. No, it is not any better to have every class have a special variable that indicates that the constructor failed. No, having empty constructors is not the answer, and it is certainly not going to help with destructor calls (the C++ standard library actually requires some destructors to silently fail because of the issues with error reporting).
评论 #6311912 未加载
BIackSwanover 11 years ago
Exactly fits the philosophy of Google Go - <a href="http://blog.golang.org/error-handling-and-go" rel="nofollow">http:&#x2F;&#x2F;blog.golang.org&#x2F;error-handling-and-go</a><p>I think his point of there being easy syntax for multiple returns is critically important to make this sort of error handling non annoying - which Go does remarkably well.<p>I think this factor has a lot to contribute to the fact that you get the warm fuzzy feeling after your code compiles. You feel confident that you have already handled all the error cases (that you care about) in your code.<p>EDIT - Obligatory nitpick accepted. ;)
评论 #6310897 未加载
评论 #6311189 未加载
评论 #6311453 未加载
评论 #6310906 未加载
stan_rogersover 11 years ago
The discussion around that time was interesting (though distributed around the blogosphere); Ned Batchelder had recently argued the opposite (and updated the argument specifically to take Joel&#x27;s article into account)[0][1]. It was at about that same time that Damien Katz was becoming firmly convinced that Erlang and crash-only behaviour would be the way to go in designing CouchDB[2][3]. (Both Damien and Ned were at Iris&#x2F;Lotus working on Notes and Domino, and I was a Domino dev at the time.)<p>[0] <a href="http://nedbatchelder.com/blog/200310/joel_on_exceptions.html" rel="nofollow">http:&#x2F;&#x2F;nedbatchelder.com&#x2F;blog&#x2F;200310&#x2F;joel_on_exceptions.html</a> [1] <a href="http://nedbatchelder.com/text/exceptions-vs-status.html" rel="nofollow">http:&#x2F;&#x2F;nedbatchelder.com&#x2F;text&#x2F;exceptions-vs-status.html</a> [2] <a href="http://damienkatz.net/2004/08/crash-only-software.html" rel="nofollow">http:&#x2F;&#x2F;damienkatz.net&#x2F;2004&#x2F;08&#x2F;crash-only-software.html</a> [3] <a href="http://damienkatz.net/2004/09/crash-only-software-revisited.html" rel="nofollow">http:&#x2F;&#x2F;damienkatz.net&#x2F;2004&#x2F;09&#x2F;crash-only-software-revisited....</a>
olegpover 11 years ago
If you&#x27;re catching exceptions all over the place, or worse using them for flow control as part of normal operations, you&#x27;re doing it wrong. Exceptions should indicate a major error that you can&#x27;t easily recover from and as such should be caught and logged at the top of the stack, i.e. the main thread run method or request handler.<p>When used that way, they give you very useful information as to what went wrong and where, while making your program more robust and resilient to errors. We&#x27;ve found this to be the case time after time at <a href="https://starthq.com" rel="nofollow">https:&#x2F;&#x2F;starthq.com</a>, which runs on Node but uses fibers via <a href="https://github.com/olegp/common-node" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;olegp&#x2F;common-node</a>.
评论 #6311149 未加载
评论 #6311091 未加载
评论 #6311216 未加载
mwshermanover 11 years ago
I am not a huge fan of exceptions per se, but it’s important to understand that they are a heuristic for minimizing ‘worry’ about things that are unlikely. I am not saying it’s a good thing, I am saying it’s the way people naturally work.<p>Let’s say there is a function that’s 20 lines long, and if you did a thorough analysis of possible error conditions, regardless of likelihood, you might come up with 50 or more.<p>We are not going to write code to address all 50 possibilities from the start. Instead, we are going <i>de facto</i> to wait and see what fails in the real world, and address them as we discover them, because we value our time. We make an economic distinction between a 1-in-1,000 problem, and a 1-in-1,000,000,000 problem.<p>Is this un-robust? Yes. Are we allowing exceptions to be a control-flow catch-all? Yes. Would a Go-like approach of simply returning error conditions reduce bugs? Probably. But it’s important to recognize programmers’ ‘revealed preference’ for exceptions.
评论 #6311080 未加载
dsegoover 11 years ago
This is a problem of architecture. Should you mix error handling with application logic? You have to handle errors somewhere, but they pollute the otherwise clean problem-solving code. One solution is to just let the exceptions bubble up and the other is to handle them immediately. If you let them bubble up, you can have a separate module that can do the right thing, notify the user, restart the app or something else. This way, the error handling is somewhat cleanly separated into its own thing. Sometimes you want to handle errors immediately, because only the code where the exception happens, knows how to deal with it. This is where return codes might be better. A lot of it depends on the desired behaviour. Sometimes you want the software to immediately exit or restart if there is a critical exception, sometimes you can safely ignore errors if real-time experience is more important. Sometimes all you want is to log the exception and&#x2F;or notify the user. Does anyone have experience with aspect-oriented programming and does it help solve any of these problems?
jeffdavisover 11 years ago
I think there is reasonable consensus about some software engineering best practices:<p>1. Avoid action-at-a-distance and side-effects that are hard to reason about.<p>2. Use immutable objects and values rather than references and pointers.<p>3. Avoid intricate control flow with many branches.<p>4. Greater isolation of processes&#x2F;threads (actor model).<p>5. Use systems and platforms with simple and strong guarantees (e.g. ACID) that are easy to reason about. Special cases and nuances to the underlying platform should be avoided.<p>6. Use tools with good support for static analysis (e.g. a good type system with a compiler that can understand it).<p>Exceptions seem to violate #1, #3, and #6.<p>These rules only apply to software engineering; that is, the reliability, robustness, long-term maintainability, and total project development cost (including maintenance and support).<p>Of course, there are other considerations, such as: performance, the time to achieve the minimum viable product, how much developers like the tools, how &quot;hackable&quot; it is, or utility for research purposes. These other concerns may be a good reason to violate the above rules.
评论 #6313782 未加载
Piskvorrrover 11 years ago
&quot;Monday, October 13, 2003&quot; - more like &quot;the old new GOTO&quot;; but apart from the out-of-the-blue rant about PHP (version 4, I guess?) at the bottom, this still seems applicable.
评论 #6310745 未加载
dicroceover 11 years ago
I don&#x27;t use exceptions for normal flow. I use them for errors.<p>While it is true that exceptions create innumerable code paths through a function, RAII makes that manageable. If you&#x27;re not taking advantage of RAII in your C++ code, you might as well be writing C code.
FreeFullover 11 years ago
Some Haskellers treat exceptions as something that you only use if the program has entered an unrecoverable condition and needs to crash.
评论 #6310836 未加载
评论 #6310990 未加载
评论 #6310833 未加载
michaelwwwover 11 years ago
<i>&gt; [as an alternative to exceptions] &quot;It is true that what should be a simple 3 line program often blossoms to 48 lines when you put in good error checking, but that&#x27;s life </i><p>Was he being serious? I&#x27;d rather not wade through all that error checking cruft to see normal flow. Exceptions (or goto) don&#x27;t create buggy hard to read programs, people do.
评论 #6311305 未加载
评论 #6311056 未加载
mamcxover 11 years ago
The advantage of exceptions is the ability to pass back the error and make mandatory dealing it (even if ignoring).<p>Exist a way to have both styles, cleanly?<p>I have thinking in how could look a language where objects, like in UNIX pipes, have stdout &amp; stderr, and if stderr is consumed (returning codes) the exception is handled, but if stderr is not consumed, then raise it?
rwallaceover 11 years ago
Most of the discussion about exceptions tries to think about it in abstract terms, which doesn&#x27;t work. The point of exceptions is a very concrete one: often the code that runs into an error and the code that handles it are separated by ten levels of function calls. Without exceptions, the logic for detecting and passing on the error has to be duplicated in every function in every one of those levels.<p>Exceptions are arguably the one feature of C++ that isn&#x27;t just syntax sugar over C, the one feature that makes the language fundamentally more expressive: they reduce a certain kind of code complexity from O(N) to O(1).
detrinoover 11 years ago
Forcing a function call to handle an exceptional condition when it doesn&#x27;t know how doesn&#x27;t really add anything but bloat to your source code (violating DRY). It&#x27;s interesting the author mentions goto, because without exceptions goto is often the most reasonable but more error prone way to handle cleanup. C++ solves this using RAII, if you need something to run before the end of the scope, stick it in a destructor. This is very easy and far more composable.
samatmanover 11 years ago
While I&#x27;m not familiar with the Erlang paradigm that inspires it, the dire[1] library in Clojure is designed to decomplect error handling from code that may generate an error. I like this approach a lot.<p>[1]: <a href="https://github.com/MichaelDrogalis/dire" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;MichaelDrogalis&#x2F;dire</a>
mtdewcmuover 11 years ago
&gt; This is ugly and annoying but it&#x27;s better than getting magic unexpected gotos sprinkled throughout your code at unpredictable places.<p>The proper analogy would be not GOTO, but COMEFROM, no? A catch block is basically a COMEFROM. :)
alexlamslover 11 years ago
<a href="http://nodejsreactions.tumblr.com/post/59877403633" rel="nofollow">http:&#x2F;&#x2F;nodejsreactions.tumblr.com&#x2F;post&#x2F;59877403633</a>
shizamhnover 11 years ago
As a side note, at least in Objective C, blocks are a great way to return multiple values (including errors) and deal with them immedately.
spo81rtyover 11 years ago
You can make methods easily return multiple values in C# with Tuples. They are very handy.
评论 #6312974 未加载
评论 #6312161 未加载
hacknatover 11 years ago
This old gem, huh?
zzzcpanover 11 years ago
Sure, exceptions are bad most of the time. But sometimes they are really useful, like in heavily recursive code, i.e. recursive parsers. Catching exceptions in a single top level function and throwing in every other one makes code much cleaner, since you don&#x27;t have to propagate and handle errors on every function call and you have single exit point on top level function anyway.