Thanks for restarting the discussion of this topic, Gilles.
Here is a first attempt at some principles for exceptions management
in [math], followed by an illustration using the ConvergenceException
case discussed in MATH487. The principles are no doubt incomplete
and some may be wrong and/or not acceptable to the community. Lets
try to find consensus on a simple set of principles that we can agree
on and use as a guide in the 3.0 refactoring and new development. I
will update the Developers Guide with what we eventually agree to.
0) Exceptions generated by [math] are all unchecked.
1) All public methods advertise all exceptions that they can generate.
2) All exceptions inherit from the base class, MathRuntimeException
3) Whenever possible, methods fully specify parameter preconditions
required for successful activation. When preconditions are violated,
a MathIllegalArgumentException should be thrown. Subclasses of
MathIllegalArgumentException may be used to represent common parameter
contract violations (for example, NoBracketingException). Exception
messages must contain sufficient information on parameter values to
determine the exact precondition failure.
4) Exceptions generated by [math] make sense without knowing
implementation details other than those stated in the public API. For
example, a NoBracketingException makes sense thrown by a solver that
has an API precondition requiring that initial points bracket a root.
This exception does not make sense, however, thrown by an inverse
cumulative probability estimator.
Together, 3) and 4) imply
5) MathIllegalArgumentException should only be thrown in situations
satisfying 3)  i.e., unless the preconditions can be exhaustively
provided so that what arguments are "illegal" can be specified fully
to the caller, different exceptions should be thrown on the event of
failure. For example, the exact domain of successful activation of a
solver or quadrature method may be impossible to specify because of
numerical properties of the method. If a solver fails to find a root
or a quadrature method fails to converge for a given set of
parameters, *unless those parameters violate the advertised
preconditions* it is not appropriate to throw
MathIllegalArgumentException. Domainspecific exceptions need to be
defined for these cases. For example, SingularMatrixException should
not inherit from MathIllegalArgumentException unless it is only thrown
in situations satisfying 3) . All current uses of
SingularMatrixException do satisfy 3), though the javadoc in some
cases needs a little cleanup to make it clear how singularity violates
the contract. My HO is that it would be better for
SingularMatrixException to not extend MathIllegalArgumentException,
substituting instead either just MathRuntimeException or a linear
domainspecific parent (shared by the other matrix exceptions).
Now on to the ConvergenceException example. Many of our algorithms
amount to generating a sequence of values, hoping that the sequence
converges (really "gets Cauchy enough") and returning an estimate of
the limit of the sequence. Thus far, convergence is always in an
incomplete metric space and we usually have the extramathematical
issue to deal with that one form of divergence is becoming NaN.
Convergence failure happens when arguments are outside the
effectiveness range of the algorithm. It is often impossible to state
precisely in preconditions exactly what the conditions are on the
parameters that will lead to failed convergence. This is especially
true when the implementation code contains bugs :)
Failed convergence manifests in three ways: a) maximum iterations
exceeded without meeting the convergence criteria b) iterates diverge
to an infinity an infinite result is not correct c) iterates "diverge
to NaN" and NaN is not correct. I suggest therefore, that we define:
ConvergenceException extending MathIllegalStateException or even just
MathRuntimeException;
MaxIterationsExceededException extends ConvergenceException, including
the max iterations as part of its state and message;
IterationRangeException extends ConvergenceException, including the
out of range value encountered and what element of the sequence
attained the bad value (this allows values other than NaN or
infinities to count as "divergence").
We could also add InfiniteIterateException and NaNIterateException
extending IterationRangeException for these cases.
I have often wanted to know how far out in the sequence one of the
values becomes infinite. Capturing this information in the exception
and including it in the message would be an improvement, IMO. The
fact that you *can* do this in the setup above is an illustration of
why I like domainspecific exceptions.
Phil

To unsubscribe, email: devunsubscribe@commons.apache.org
For additional commands, email: devhelp@commons.apache.org
