5 ms·
I must admit I use exceptions heavily for validation, e.g. checking input at API bounds. It makes the code fairly clean. I would imagine this is considered bad
by nogridbag 4y ago
I must admit I use exceptions heavily for validation, e.g. checking input at API bounds. It makes the code fairly clean. I would imagine this is considered bad practice, but if there was no overhead this seems preferable over wrapping every call in some wrapper object. Any good links to further info on this?
- viraptor 4y agoIf you check for actual exceptional cases, you have next to no overhead. The overhead comes from creating the exception environment and going up the stack in unusual ways. For validation where most data is correct, this should have next to no impact.
- narag 4y agoFood for thought: what are the expected consequences of the exception? If the error will stop the program flow and show a warning dialog to the user, it's useless to think too much about performance. More or less the same if it's going to log some message and abort the operation. What is usually frowned upon is using the exception as a kind of goto for normal flow of the program. Exceptions should be... the exception. Otherwise all this performance brouhaha is a waste of time.
- em3rgent0rdr 4y ago"Exceptions should be... the exception." :)
- arcticbull 4y agoThe problem is exceptions have entirely opaque flow control. They're the opposite of a goto statement: a comes-from statement if you will. Flow control could originate literally anywhere down the stack and that makes reasoning about what's happening very difficult. Depending on the language it can also have a super broad and ever-changing surface area.
- groestl 4y agoThere's nothing opaque about having an implicit potential return after every line as well as an implicit additional error result value. Think Go, but without the ceremony.
- kortilla 4y agoThis is not correct, a “comes-from” statement would still be the same behavior as a goto except it’s defined at the label and there is no “goto” at the departure line. Exceptions are just “goto whatever catch is in the call stack”. It’s still completely obvious when you see a throw statement that it can throw, and static analysis can tell you exactly what can be thrown by each function.
- ilyt 4y agoAnd it is still opaque where it goes to the programmer when they see it in code. The fact you can use tools to find where it might land (yeah, no shit, you can do same for goto...) is just a mitigation to the problem.
- rightbyte 4y agoIt unwinds the call stack until a catch. It is the same "problem" as not knowing where a return will return to.
- arcticbull 4y agoReturn only ever moves up the stack one level. That makes it really easy to reason about. This can move up the stack an unlimited amount, and the handler has to be prepared to properly deal with the current state, no matter where it comes from.
- kortilla 4y agoThis is no different than returning an error in go far down. You don’t know how far up it will be passed or handled.
- grishka 4y agoException is a way to return from a function abnormally. So yes, they are for exceptional conditions. IMO it's perfectly fine to use them for input validation. The Java standard library itself does it all the time.
- knorker 4y agoJava is the... uhm... exception here. That's not how idiomatic C++ is. Nor Rust. Nor Go. One of Java's (incl standard library) main design flaws is overuse of exceptions. It should not be emulated. It's too late to fix Java, but that doesn't make it a good idea.
- twic 4y agoRust uses Result. Checked exceptions are Java's analogue of Result.
- knorker 4y agoI disagree. Exceptions are a fundamentally different control flow. Exceptions are exceptions. Return values are not. I would not call std::optional in C++ any form of checked exception, and the difference isn't that std::optional doesn't carry value-missing metadata.
- grishka 4y agoSo what do you do in C++ if the input to your function is not what you expect?
- gilbetron 4y agoReturn an error or fatally exit the program, depending.
- grishka 4y agoIf you return an error, it needs to be checked for in every place where this function is called. Yes, I know C libraries and OS APIs do this often, but that's C, it's the only thing it can do. This just invites human error. Besides, it's often desirable to handle multiple different error conditions (arising from different steps as you process the input data) in one place, which is complicated with this approach. Java-like exception handling makes it easy to handle all errors in a single place and be sure none go unnoticed. This is especially useful when you're accepting external input (a file, a network packet/stream, an HTTP request, etc). If you exit the program on error, this does work in some cases like command-line utilities, but your users would not be happy if your GUI app crashes when you open a malformed file.
- foolfoolz 4y agovalidating with exceptions is good because it makes your code much cleaner to read. the cost benefits of reading and easy maintainability is extremely high the example shows an extra time of 500nanoseconds when not throwing. this is 0.005 milliseconds. if your api takes more than 1ms then changing it to not throw will not be noticeable. even if the exception time cost was 10x higher and it took 0.05ms longer it would not be noticeable
- yawboakye 4y agoso long as you’re not catching the exception and figuring out how to continue execution of the same function i think you have a good use case here. it’s no different than `assert`ing invariants at the top of a function, for example. if invariant is violated, the call should be aborted.
- xxs 4y agoIf you involve |API| an external input, no one cares about the validation, that actually succeeds in virtually all cases. You should care only about the fast path - the rest are quite irrelevant (outside DoS attempts)
- ilyt 4y agoThink that's probably the best use case actually - API bounds are often "just check a bunch of stuff, from AA thru data validity to whether connection finished cleanly" so just putting catch over whole request handling is easy to reason about.
- sorokod 4y agoIt does sound abusive since validations are expected to fail and so should not require an alternative way to return their outcome.
- commandlinefan 4y ago> I use exceptions heavily for validation This fits within my understanding of a reasonable use for exceptions - usually these are in the form of assertions, which themselves throw exceptions but can be turned off at runtime if you don't expect to ever see this condition in real production circumstances.
- noobermin 4y agoI hate to say it but you are using goto. Goto is used often in C parsers for a reason, because it is easier to reason that way when you're validating something rather than using deeply nested branches. People shit on goto because of dijkstra's paper but few people have even read that paper and fewer even know that it is the origin of "x considered harmful" meme. Goto is a boon. Anytime people use exceptions like how you are you're just admitting you're itching for a goto and your language doesn't provide it. And thus you shouldn't clutch your pearls when others use it in c.