3 ms·
So exceptions do add structure as to where you can go _to_ but they serve the same purpose in where you can come _from_ Its a little easier to trace since you a
by dkhenry 14y ago
So exceptions do add structure as to where you can go _to_ but they serve the same purpose in where you can come _from_ Its a little easier to trace since you are scope bound, but its still harder then being able to trust the control flow of your code. Additionally because you can't trust control flow of your code ( since any time the sub routine can essentially longjump to some place higher in your stack) you are now required to context wrap all your code in try blocks essentially implementing bookkeeping that the compiler will do for free if you just design your code in a sane manner.
This is why java implemented typed exception throwing because it the only way to have some semblance of safety when programming with exceptions. I am even more disheartened to see that the author uses my beloved scala and in still trying to do this kind of nonsense, when we have plenty of good tools at our disposal to negate the use of exceptions for control flow.
- mcherm 14y agoI'm not completely sure I am understanding you. I think that RAISING exceptions is just a non-local exit point, like a break or return which does not make it difficult to reason about one piece of code in isolation from others. I think that CATCHING exceptions is a clearly marked 'entry' point: one can only arrive in an exception handler from an exception raised within the corresponding try statement, and the place that you arrive is clearly marked. The one bit that is more confusing is throwing right through without an exception handler: in other words, code you call might raise an exception which your code does NOT catch, and thus exit your function prematurely: you might thus allocate some resources and fail to deallocate them safely. Are we saying the same thing here?
- dkhenry 14y agoSomewhat. You are correct to say were know that the exception was raised in the try block so we have an idea about where it came from, but unless each try block is one statement long you don't know where the exception came from . That's the disconnect. When in a try/catch block you know where your going ( the catch ), but you don't know where you came from. That is almost as problematic as GOTOs in that planning for all program states is once again a headache ( did I open that socket , is that memory free'd ,... )
- mcherm 14y agoI see what you are saying. I think I avoid this problem by having a policy of not modifying fields arbitrarily within a try statement. Let me try to give some examples. I write things like this: Person p = getThePerson(id); try { storePersonToDatabase(p); } catch(DatabaseException err) { generateAlert('Could not save person'); } doMoreProcessing(p); In this case I know that p was initialized because it happened outside of the try statement. But I try never to do things like this: Person p = getPrimaryAccountHolder(); try { storePersonToDatabase(p); p = getSecondaryAccountHolder(); storePersonToDatabase(p); } catch(DatabaseException err) { generateAlert('Could not save person'); } doMoreProcessing(p); If I did that, then there would be no way to know whether p was the primary account holder or the secondary after the try statement when I call doMoreProcessing(). On the other hand, it's perfectly OK for me to do this: Person p = getPrimaryAccountHolder(); try { storePersonToDatabase(p); Person p2 = getSecondaryAccountHolder(); storePersonToDatabase(p2); } catch(DatabaseException err) { generateAlert('Could not save person'); } doMoreProcessing(p); ...because with this pattern I don't know, after the try-catch, whether the variable p2 has been initialized or not, but I also don't care because it is out of scope and can't be used. If I didn't follow this practice, then I think the problem you describe would be an issue for me: not knowing which of several possible locations was the source of the exception would mean I didn't know how the variables had been set. Interesting... I learned something today.
- dkhenry 14y agoI think we are on the same page now. What your describing works well If you do it _everywhere_ and also _require_ exceptions to be handled, much like Java does (mostly) in c++ its a total crap shoot since destructors don't run if you pop their stack.