5 ms·
Please, please, please do not throw anything that is not derived from Error. Throwing literals or other things makes error handling so much less predictable, st
by hambes 5y ago
Please, please, please do not throw anything that is not derived from Error. Throwing literals or other things makes error handling so much less predictable, stable and useful. throw/catch is already bad, let's not make it worse than it needs to be.
- onion2k 5y agoNonsense. You can treat Throw like a fancy "goto the nearest catch" if you want to. It works fine.
- shadowgovt 5y agoYes. In every way that goto is considered harmful it works fine.
- smt88 5y agoIf you're using throw for control flow, something is deeply wrong with your code.
- the_other 5y ago`throw` is a control flow instruction. Simply using it at all controls flow within your code. Are you suggesting never to use it?
- golergka 5y agoI think that the parent comment means "for control flow unrelated to error conditions".
- smt88 5y agoI am suggesting to use it to throw exceptions. This narrow purpose is subtly hinted at by its name.
- the_other 5y agoI don’t see how it’s hinted in the name. “Throwing an exception” is a phrase from within computing that exists because the feature exists in some languages, not because it came into programming from English. There’s also nothing about “exception” that means “error”. If anything, modelling exceptions as errors is the anti-pattern. If you modelled all exceptions as descriptors, you could save Errors for when something actually goes wrong. Honestly though, I’m employing Socratic argument. I am only defending this position to learn about the opposite.
- regularfry 5y agoNow I'm wondering about throwing functions as continuations. This sounds incredibly messy. I love it.
- emteycz 5y agoWhy not generators then?
- regularfry 5y agoBecause that wouldn't be perversely abusing a language feature for completely the wrong purpose.
- shadowgovt 5y agoI... May have done something like this once in a scripting language interpreter to implement return and break. Not in JavaScript. And using continuations passed down from above would have been the much more correct way to do things.
- onion2k 5y agoThere isn't though. Exceptions are flow control. There's nothing particularly special about them internally in a JS engine. https://ripsawridge.github.io/articles/exceptions/ https://ripsawridge.github.io/articles/exceptions/
- smt88 5y agoI know. But what happens when someone inherits code that has a lot of this in it? They read a line, get to a throw, and then... how do they find all the catches that might apply? Using that pattern is like a guarantee that your code will be spaghetti and meatballs. This concept is so fundamental that it's even the topic of possibly the most famous CS article ever written[1], and I'd even argue that throw/catch is the worst-possible version of goto. 1. https://en.m.wikipedia.org/wiki/Considered_harmful https://en.m.wikipedia.org/wiki/Considered_harmful
- onion2k 5y agoWhen Dijkstra wrote his article [1], in 1968, I have no doubt he was correct. His point was essentially that code should reflect the flow of the application as closely as possible because it's immensely hard to keep everything in your head if it doesn't in the context of programming in 1968. The thing is though, tools have moved on in the past 54 years. Seeing the flow of your code is a lot easier now. Debuggers are amazing things. While I think his broad point (that code should be as simple and easy to follow as possible) still stands I don't really agree with it here. "goto considered harmful" could be used to argue that anything that changes and obfuscates the flow of a program when you compare the source to the compiled output is bad regardless of what it is, and that's plain silly. We'd have to throw away all manner of useful things like exceptions, macros, inheritance, etc. I like Dijkstra's writing a lot, and he did groundbreaking work, but we have to remember to consider everything in the context of when it was written. This is a good example of that. [1] http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html http://www.u.arizona.edu/~rubinson/copyright_violations/Go_T...
- smt88 5y ago
- dspillett 5y agoThat sounds fine as a quick hack in your own code that you never intend others to use, but if something like that escapes your library into calling code (isn't always properly trapped by your exception handling due to a bug) you are asking others to deal with a significant change to a commonly accepted standard behaviour.
- the_other 5y agoIsn't "ensuring you always throw Errors" the same level of code cleanliness as "keep a top level catch in your code" or "document the errors and exceptions of your API"? If you make your team do one, you can make them do another.
- chrisco255 5y ago> you are asking others to deal with a significant change to a commonly accepted standard behaviour. For a JavaScript developer, that's just Tuesday.
- dspillett 5y agoAnd that Tuesday lasts all day until Friday. Sounds about right.
- sirsuki 5y agoIf you need to use a rejection as a meaningful thing other than an actual exception then it really isn’t an exception is it? Instead fulfill the promise with an object that actually represents the state. Perhaps with a status property. Otherwise your code is going to look like a hot mess and you’ll just confuse generations of developers. Just because you can does not mean you should.
- mcherm 5y agoCan you provide some examples of specific situations in which throwing objects not derived from Error causes difficulty? I ask for two reasons. First, because I find argument from authority to be a very annoying logical fallacy. I have actually heard people argue that in Python one should never use an exception to exit a loop, because "that's not how exceptions are supposed to be used". The people making this argument don't realize that every for loop in Python is always exited via an exception. My second reason for asking is that I think your examples might all fall into certain categories. For instance, maybe there is a good argument for "never throw things not derived from Error in a way that they will escape your library, but within one library/module it's a perfectly fine technique". Looking at specific pros and cons would help uncover the cases where it is most and least harmful.
- spicybright 5y ago> The people making this argument don't realize that every for loop in Python is always exited via an exception. It's just all memory addresses under the hood, so why bother with variable names? Only throwing exception objects is a layer of abstraction that makes error handling easier to handle. Nearly all python libraries follow this pattern, and it's extremely easy to pass any variable you want to your custom exception for you to handle however you want.
- shadowgovt 5y agoIf you're throwing weirdly shaped things inside code other people don't need to interface with, that's fine. Go nuts. You'll be creating a circumstance where any new person working with your code has to learn that you're doing something strange, but you won't really be impacting anybody else. The fact that JavaScript allows non-Error-derived values to be thrown means that the first thing that any code that works with a thrown value has to do to be technically correct is runtime type inspection. You can't even assume the thrown value has a stack trace attached to it. So while technically the ship has already sailed, we add further complication to everyone's error handlers when we emit non-Error values via throw... Everyone's catch code has to grow support for handling whatever Byzantine type we've decided to toss out of our code today.
- jitl 5y ago