Re: Invalid parameter handling
Kaba schreef:
How do you react correctly to an exception that
effectively says "you have a bug somewhere"? You don't. In my opinion,
it is very wrong to throw an exception here. Exceptions are a handy
tool, but one should keep in mind that:
* they should only be used in a level high enough so that their handling
doesn't litter the program.
* they should only be used if they can be reacted upon.
std::vector's at() fails both of these criterions.
I once wrote an application where my boss had the idea of putting a
try-catch(...) around the menu handling function. If an exception of
any kind was thrown, the application showed a messagebox saying that
an error occurred and that the user should save his work. That would
nicely handle the invalid index.
The word processing program indexes the std::vector
using the at() function. But now at() correctly throws an exception,
which isn't catched at all because it is such a low-level thing and the
word processor eventually delivers a report to the writer that "there
has been an internal error and the program has to be shut down". If
there are no autosave features or such, the work is all lost.
This is not robust. But by this example we see what would be robust:
that we could keep the program running as long as possible. In this
case, the off-indexing wouldn't probably be that fatal: if we could just
return a null pointer as the callback function and avoided calling any
nullpointer function, we would just end up doing nothing.
In the case of a wordprocessor this makes sense, but not in other
applications. Consider an application that updates bank accounts. If
an error occurs, the application should terminate ASAP, and the
developer that maintains the application comes to see what happened
and how to fix it. Otherwise it could e.g. put the weirdest numbers
on the accounts. And it's better to write one letter with apologies
to a customer than a million.
Now that I have preached over what I see as a better world, what am I to
do to achieve it? Well, here is the start:
http://kaba.hilvi.org/project/texts/parameters.htm
which is a text of mine that tells you essentially the same as this post
and some techniques to make it a reality.
Essentially you mention two things: some macros to handle errors, and
a technique to use them to react on invalid parameters.
Many similar macros have been written for C++. ModAssert, that I
wrote, is the most advanced package I know of, see
<http://modassert.sourceforge.net/>. Your example would become
MOD_CHECK(rbMORE(aPositiveNumber, 0), return 0);
MOD_CHECK_P(someNumber, (someNumber & 1) != 1, ++someNumber));
In a future version of ModAssert you could do about the same with
MOD_VERIFY_B, which is better because MOD_CHECK is actually meant for
expected errors, not for bugs.
The technique to react on invalid parameters has its advantages in
critical applications, and I believe it is not very new. E.g. in
software that controls a plane it is necessary to correct bugs
(that's why I want to add MOD_VERIFY_B).
As to the default parameters in generic functions (mentionned on his
webpage), you could write a class template and specialize it for
every type that you use it with:
template <typename T> struct DefaultValue
{
static T value;
};
template <typename T>
T DefaultValue<T>::value = T();
template<> struct DefaultValue<char>
{
static char value;
};
char DefaultValue<char>::value = '?';
You can even write more than one such class templates, one for each
set of problems.
--
Mark dot Van dot Peteghem at q-mentum dot com
http://www.q-mentum.com -- easier and more powerful unit testing
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]