5 ms·
> Don't throw exceptions if you can handle the error and continue where you left off. Exceptions is for when you can't continue. Yes, although quoting that exa
by dmethvin 15y ago
> Don't throw exceptions if you can handle the error and continue where you left off. Exceptions is for when you can't continue.
Yes, although quoting that example doesn't support the assertion. JSON.parse is a library function. How can it judge whether the caller can continue or not just because the JSON cannot be parsed?
> Think of throwing as a way to roll back transaction, stop whatever you were trying to do, and go back to the last consistent state.
Any try block that is larger than one atomic operation can become a nightmare to roll back, since the catch gives you no idea how far it was into the block, what resources were allocated, etc. So although try/catch avoids the hassle of checking state after each operation, you pay for it on errors.
- azov 15y ago> JSON.parse is a library function. How can it judge whether the caller can continue or not just because the JSON cannot be parsed? Don't make assumptions about the caller, throw if your library can't continue. > So although try/catch avoids the hassle of checking state after each operation, you pay for it on errors. If your language supports RAII (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initial...) you get a free ride. Otherwise you have to write non-trivial cleanup code regardless of how you return errors. Try/catch (and especially finally) helps a lot because you get to group all your cleanup in one place. With error codes the code looks something like: a = acquire(A) if (!a) return b = acquire(B) if (!b) { release(a) return } c = acquire(C) if (!c) { release(a) release(b) return } ... This is a maintenance nightmare. It's hard to see what the code is doing because the real logic is hidden between piles of error handling stuff. If you add a new resource acquisition in the middle you have to go over every statement that follows and modify error handlers. And don't you dare changing the order of statements, because that basically forces you to rewrite the whole function. Believe me, you don't want this in your code, exceptions are your friend :)
- regularfry 15y agoNo, the way to handle that pattern is with nested gotos: a = acquire(A); if (!a) goto err_a; b = acquire(B); if (!b) goto err_b; c = acquire(C); if (!c) goto err_c; do_stuff(a,b,c); err_c: release(b); err_b: release(a); err_a: return; This is precisely why goto is not universally evil.
- gue5t 15y agoConsider: a = acquire(A); if (a) { b = acquire(B); if (b) { c = acquire(C); if (c) { do_stuff(a,b,c); } release(b); } release(a); } return;