I prefer to throw when an error occurs. This ensures me that the execution
of the calling function stops. Without throwing I might forget handling the
error condition and such errors are hard to find during test.
Niels Dybdahl
My preference, as the designer and developer of a function, is to provide
adequate documentation about the behavior and abilities of said function.
As the user of functions that others have developed, I want to see such
documentation as well.
My reasoning is that at any location in a given fragment of code, an
error may occur. Some errors are more likely than others. Exception
based error reporting enforces the user to wrap all code levels with
appropriate exception handling code. This must be done often enough
that the user can actually find and correct the cause of an error
when it occurs. For any given level of functionality, there are many
possible errors to report -- whether they may be from exceptions or
other known sources.
Given a well documented interface, the user can then decide what
is an appropriate use for their needs. This includes handling
unexpected conditions.
Users need to handle errors at a reasonable level. Your preference
to use an exception to report "an expected file error" may be appropriate
for one developer and not another.
My preference for using exceptions is to use them very sparingly
and with good cause. Before exceptions were common, return codes
and other methods were commonplace. The user had to decide at what level
to check for these unexpected conditions. Exceptions give us a different
method of reporting errors. Now users are faced with handling both
methods all of the time. Your code could be quite complicated for
handling information (expected and unexpected behavior) for any non-trivial
function. When designing interfaces, please make it easy to understand
what the expected behavior is. I should be able to use nearly all
interfaces by reading just the interface documentation (.h and other files).
You should make it easy for the user to handle all errors and behaviors
appropriately. That has different meanings for different environments.
So, consider your user base when designing an interface.
Your suggestion that the interface provide both non-exception and
exception based functions is a good one. However, when that function
is non-trivial, you may find that writing both versions at a level that
can handle all errors appropriately may be a daunting task. The two
functions may not even look the same. Keeping them in-sync could be
difficult.
David