TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Exceptions (2003)

63 点作者 abl超过 11 年前

22 条评论

beagle3超过 11 年前
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 未加载
betterunix超过 11 年前
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 未加载
BIackSwan超过 11 年前
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_rogers超过 11 年前
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>
olegp超过 11 年前
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 未加载
mwsherman超过 11 年前
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 未加载
dsego超过 11 年前
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?
jeffdavis超过 11 年前
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 未加载
Piskvorrr超过 11 年前
&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 未加载
dicroce超过 11 年前
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.
FreeFull超过 11 年前
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 未加载
michaelwww超过 11 年前
<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 未加载
mamcx超过 11 年前
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?
rwallace超过 11 年前
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).
detrino超过 11 年前
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.
samatman超过 11 年前
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>
mtdewcmu超过 11 年前
&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. :)
alexlamsl超过 11 年前
<a href="http://nodejsreactions.tumblr.com/post/59877403633" rel="nofollow">http:&#x2F;&#x2F;nodejsreactions.tumblr.com&#x2F;post&#x2F;59877403633</a>
shizamhn超过 11 年前
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.
spo81rty超过 11 年前
You can make methods easily return multiple values in C# with Tuples. They are very handy.
评论 #6312974 未加载
评论 #6312161 未加载
hacknat超过 11 年前
This old gem, huh?
zzzcpan超过 11 年前
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.