Fault oblivious software
When faults occur in software they are in nature unanticipated, even though we may know that they will occur. The prevailing paradigm for such is currently, throw the exception. I call that the Pilate syndrome, where the developer washes his hands of the error. This behavior leads the crashes because unhandled i.e. unanticipated exceptions leads to that.
Dont throw exceptions. Now here I am going to violate a lot of correctness principles, because when I advocate for not throwing exceptions, then what should be done? Well nothing. If you try to open a nonexisting file, well you get an file object. When you try to read from it you get a default character, when you read its length you get zero.
All modules that behaves oblivious to faults, will not crash. What happens when faults occur then? The software will be missing in functionality (i.e. something does not work). The result is the same as if it crashed, that the function didnt work. But since the software didnt crash it might act reasonably anyway.
It takes more work to write your libraries to encapsulate faults like this. For debugging purposes a log will suffice, so where you would usually throw your exception, just make a log entry. If the log is an interface, you can if you like display a dialogbox, and halt the program afterwards if you really want to simulate the crash.
Dont throw exceptions. Now here I am going to violate a lot of correctness principles, because when I advocate for not throwing exceptions, then what should be done? Well nothing. If you try to open a nonexisting file, well you get an file object. When you try to read from it you get a default character, when you read its length you get zero.
All modules that behaves oblivious to faults, will not crash. What happens when faults occur then? The software will be missing in functionality (i.e. something does not work). The result is the same as if it crashed, that the function didnt work. But since the software didnt crash it might act reasonably anyway.
It takes more work to write your libraries to encapsulate faults like this. For debugging purposes a log will suffice, so where you would usually throw your exception, just make a log entry. If the log is an interface, you can if you like display a dialogbox, and halt the program afterwards if you really want to simulate the crash.

6 Comments:
"But since the software didnt crash it might act reasonably anyway."
But it might do something much worse than crashing.
For example, let's say your program is trying to clean up unused files on a hard drive. And let's say that there's a file that has a list of special system files *not* to delete. And, for whatever reason, that file is missing. Your program would think that the file's size is zero and assume that it can delete everything.
There are more disciplined ways to handle localized failures than to have every library call somehow return something.
I am not saying that the approach works in all cases. Your example is perfectly valid, but even implemented using other strategies you risk having the exact same error. The thing is that you have to anticipate most errors, but software WILL contain errors not anticipated (well - most software).
There's really nothing wrong with software that crashes. The problem is if while crashes it causes other side effects, like loosing financial transaction records, refusing to come back up, etc.
Sometimes a crash is what you actually need, to protect you from situations you didn't expect (someone deletes a donotdeletethesefiles.ini that your software uses to actually know which files not to delete)
I'm very much an advocate for allowing software to crash and burn, as long as it leaves itself in a ready to go state with enough information to let us know what went wrong.
the problem is not really throwing exceptions by itself, but throwing exceptions that you have caught and mangled and disguised beyond recognition.
Basically, if you are not going to explicitly recover from an exception, please do not catch and bury it or wrap it in your own application specific exception, only to rethrow it... instead, if its in brain-challenged java and you're forced to catch it, just wrap it in a RuntimeException and rethrow immedietly, if its in a decent language that doesn't force you to catch some types of exceptions, then just ignore it and allow it bubble upwards.
Somewhere up in the ionosphere, you need to log all exceptions, and that's really what's important. To end the rant:
When an exception occurs, either:
1. Catch it and recover from it (e.g. opening a network file? no connection, exception thrown, turn around and use the previously cached local copy)
OR
2. Log it, prefarrably waay higher up than where it occured (just incase someone else, can actually recover from it).
There really IS somethint wrong with software that crashes - word and other editors really piss me off when they crash.
I come from a time before exceptions were in the languages, and software handled faults in those days fine (or more or less as well as today).
I dont want the exception in the guise it is today no matter how comme il faut it is, and by putting my software on top of existing languages I have no other choice than cathing the error and swallow it (actually I will convert the exceptions to the optional exceptions - i.e. they only gets thrown if something catches them)
Maybe I should have said processes that crash and then we'd be talking about two closely related but still different things. You're referring to the entire system, while I'm referring to the parts that make up the whole. This distinction was not clearer before.
I've been coding in erlang for the past one year and some months, and I can honestly say that having a mechanism that aids recovering from process crashes, has kind of freed me from trying to build processes that just do not crash. Instead, I try to build temperamental processes that do crash, but are restarted by the provided mechanisms in erlang into a known good state, effectively voiding the effects of the crash. The word crash has a negative connotation to it though :)
You're absolutely right about software like Word and other editors that crash... plain irritating to say the least. Architectures like Google Chromes' that isolate tabs which can then crash and burn independently without taking down the whole browser, are a major step in the right direction. It may be even possible to attempt to restart them if enough information was available while crashing.
For server software where transactions can be retried and restarts are not interactive, what I described is I think an improvement on the norm, but its really a pain for GUI centric applications.
I don't build GUI centric applications anymore, but I would guess that having a small core that is more or less impervious to the run-the-mill crash and can attempt to restart the other parts, would be a good starting point, and then it would not be a bad idea to allow the other processes/threads crash and burn, while not necessarily taking down the entire software suite. In that case, the small core would "theoretically" crash less and when it does, it would be a good idea to let it crash.
That's why I actually advocate bubbling the exceptions, so the owning processes/thread will die fast and can possibly be restarted, instead of trying to weather the storm when not quite sure what else could be out there.
I guess various approaches have their uses.
Sounds reasonably to do that in a super multi process environment like Erlang. Actually it might be programmed to work in the same manner, provided that the other processes doesn't hang because of the crashed one.
The multi processing issue will also be tackled a little different in Dawn, than the usual methods (actor, etc). All the non standard features, does however make Dawn an experimental language, since I cannot reasonably say that I'm right about my claims, but I'm darn well gonna try them out :-)
Post a Comment
<< Home