3 ms·
>> However, I'd say that it's the async programming model that is broken, not try/catch. This is an interesting point of view, however I'm inclined to disagree
by nogden 15y ago
>> However, I'd say that it's the async programming model that is broken, not try/catch.
This is an interesting point of view, however I'm inclined to disagree on the basis that the async model is representative of how things actually happen; the imperative model is not.
In an asynchronous architecture, the developer is concerned with only the current state and the set of all events that may cause a transition from that state. Whether or not an event is the result of an error condition is irrelevant, one simply invokes a different handler.
I used to consider the asynchronous model much harder to program in, that is until I changed my thought process to work in terms of state machines. Then it actually became much simpler to program in this model since, at the handler level, one has no preconception about what should happen next, only what can happen next and how to handle each of those situations.
>> C++ is pretty nice when it comes to error handling and exceptions as resources are cleaned up on error.
There has been many a discussion about the benefits vs. pitfalls of C++ exceptions. I personally am not a fan since the lack of garbage collection means that there are situations that require lots of tedious and error prone boilerplate code just to ensure that all resources are cleaned up.
I have to admit that perhaps the nicest way I have seen of handling failure is in the concept of Monads in Haskell (and other functional languages). The ability to add the context of failure as a possibility in any computation, without requiring that computation to explicitly consider it is extremely elegant. Add to that the safety of always returning a well defined value that is fully type checked by the compiler and I believe you have a recipe for very effective error handling.
- jerf 15y ago"This is an interesting point of view, however I'm inclined to disagree on the basis that the async model is representative of how things actually happen; the imperative model is not." Have you used Erlang or Haskell? I have heard this line of defense a number of times, but always from people who have to answer "no". The claim is that it's better to let the compiler handle the issues. You're response is basically that since you learned how to more properly run what the compiler does in your head, you've done better. I would submit that's support for the idea that a compiler should be doing the work, not evidence against. What if you could skip the part where you didn't know how, then skip the part where you had to learn better, and then skip the part where you're running this algorithm in your head, and just let the compiler do it for you from day one, and probably better than you can do it even with experience? (Humans suck at maintaining invariants. It takes years of experience to even be sort of good at it, and you'll still be terrible compared to a compiler.) While you should know what the compiler is doing to your code, this is hardly any different than manually implementing the C stack on every function call. The fact that it may occasionally let you do something clever doesn't get around the fact that you really shouldn't be thinking about this on every single function call at all.
- exDM69 15y ago>> "This is an interesting point of view, however I'm inclined to disagree on the basis that the async model is representative of how things actually happen; the imperative model is not." You're absolutely correct in that many operations are executed asynchronously. However, I think that it shouldn't be the model we use to write programs. Programming is all about abstractions and the imperative model is a good abstraction which can be implemented effectively by a compiler and a runtime system. Sure, a program can be composed by maintaining a state, which changes when events occur. I just feel that it gets really hairy really quickly when you start to have several IO operations in sequence and have to start thinking about multiple error conditions. With exceptions and imperative code, you can write the IO operations one after another and catch the exceptions where they can be handled (e.g. show an error dialog in the GUI). With hand-written CPS async code you have to assign an error handler to each IO call, even if you'd want to have only one handler for several error conditions. >> "I have to admit that perhaps the nicest way I have seen of handling failure is in the concept of Monads in Haskell" I think that failures are not handled with the monad failure function any more in Haskell, but exceptions are use these days (a quite recent addition to Haskell language). A catch can only be in IO code but throw can be in either monadic or functional code.
- sbov 15y ago> I personally am not a fan since the lack of garbage collection means that there are situations that require lots of tedious and error prone boilerplate code just to ensure that all resources are cleaned up. The problem is memory isn't the only resource that needs to get cleaned up, and at least in Java, when a variable falls out of scope resources such as database connections, opened files, etc, will not instantly be cleaned up. However, with c++, as long as you're using RAII (and if you're not, why aren't you?), all a resource has to do is fall out of scope to clean it up. RAII is certainly cleaner and less tedious than anything I've seen in Java and C#.