Revision of For an I/O operation, do you prefer errors handling based on getting an exception, or having to check for an error after? from Thu, 12/08/2011 - 22:25
The revisions let you track differences between multiple versions of a post.
Comments
More details below
Currently EiffelBase I/O handling will raise an exception if an operation fails. Meaning that one should not forget about catching exceptions during I/O operations otherwise your program might simply crash and exit.
The alternative we are considering is to change that behavior to set a status flag after each I/O operation that a user would have to check to ensure the operation proceeded successfully. In that case, your program will never crash but it might not behave correctly if one forget to check for that status flag.
Which alternative do you prefer?
Exceptions caused by environmental factors
"More details here", Manu? Where?
Anyway, here are my thoughts.
The normal Eiffel approach is to raise an exception only if there is a violation of a an assertion, i.e. if the program itself is incorrect.
I/O errors (lack of disk space, expected file does not exist, etc.) are environmental conditions. Running out of disk space isn't a bug in the program. Although it isn't an absolute principle in Eiffel that exceptions should not be raised due to environmental considerations, the current EiffelBase I/O handling runs contrary to how we habitually think about exceptions in Eiffel, so there's a big risk that we won't write the necessary rescue clause. When programming in C#, sure, I would always write a try ... catch block around I/O operations. This is habitual when programming in C# (or Java or C++, etc.). It's not a habit in Eiffel.
I don't like the idea of making this a configurable option. If one programmer writes a class using the status flag option, and then another programmer reuses that class in a different system that throws exceptions for file I/O, then the class will behave differently.
Although I would prefer a status flag, exceptions do have the advantage of being more likely to be noticed by the programmer during testing. But there's no guarantee of that either. Neither option seems perfect.
The best solution would be compile-time verification that the necessary checks were being done. Something like Java's checked exceptions might be good for this purpose (although we definitely wouldn't want all exceptions to be "checked"). Maybe some kind of design pattern involving void-safety checks could achieve this goal. For example, opening a file might return some object for manipulating the file or else Void on failure; an object test would be necessary in order to manipulate the file and compile successfully. It's not obvious to me, however, how we could extend such a pattern to commands such as writing to a file.
I used `here' to mean my
I used `here' to mean my comment entry. The poll interface does not let you put a detailed explanation for the question. I used the comment entry to explain a little bit more what we had in mind when creating the poll.
Peter, an exception is a very
Peter, an exception is a very helpful way of bailing. For many classes of software you cannot continue after disk full. You just gotta quit. As quitting is so often the right thing to do, having to write checks and then write the quit, is completely annoying.
But the best solution as already been found: programmers who write real world software write libraries that can do both. So depending on the use case you get an exception (the default), or you turn them off, and you deal with them manually.
Libraries that can do both
Having a configuration option that allows you to choose whether or not an exception will be thrown sounds like the worst possible solution to me, Berend, because when writing some class I have no way of knowing how it's going to behave in any given system.
But maybe a configuration option is not what you meant. Maybe you're suggesting that the option should be controlled by a command on the relevant I/O classes ... something similar to how container classes allow clients to decide whether to do object comparisons or reference comparisons. That would be acceptable, in my view.
I do think that by default it should not throw exceptions, however, due to the principle of least surprise. Eiffel programmers don't normally expect exceptions to be raised, except for assertion violations. If some client class wants an exception to be thrown then I think the class should have to opt in.
Exception or not Exception? That is the question!
We had some internal discussion about this. And there are many solutions with pros and cons.
I personally prefer the last proposal but looking at the complexity, I'm figuring that not having exceptions and not offering the opportunity to raise exception is what we should do to keep things simple.
Like eposix does: have both.
Like eposix does: have both. Default is exception, you can turn that off.
That's an option we had in
That's an option we had in mind, but I should have emphasized that we were talking about choosing the best default and want to have users provide their input on that.
best default: exceptions. But
best default: exceptions. But exceptions don't work in all cases. If you want reliable software, you need to be able to turn that off, because as soon as you have an exception, your class invariants get to an unknown state.