commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Phil Steitz <phil.ste...@gmail.com>
Subject Re: [Math] Exception handling (again)
Date Sun, 23 Jan 2011 21:10:30 GMT
On Sun, Jan 23, 2011 at 2:45 PM, Luc Maisonobe <Luc.Maisonobe@free.fr> wrote:
> Hi Phil,
>
> Le 23/01/2011 19:27, Phil Steitz a écrit :
>> 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 MATH-487.  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.  Domain-specific 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
>> domain-specific 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 extra-mathematical
>> 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 domain-specific exceptions.
>
> Wow! That is a thorough analysis and a constructive one.
>
> I fully agree with you. I'm not sure that IterationRangeException is
> needed, but that is a minor point.

I am curious why you see IterationRangeException as not needed when
MaxIterationsExceededException is, unless you think that the latter is
also unnecessary.  These are really the two logical subclasses of
ConvergenceException.  If we eliminate both of them, then we would
need an enum or something else to indicate the nature of the failed
convergence (iterates going out of range or max iterations exceeded).
>
> Concerning point 1), there are two ways to advertise the exception.
> Javadoc only, or Javadoc plus throws clause. I personnaly would prefer
> Javadoc plus throws clause

+1 for both, with throws mandatory and javadoc also for all but
trivial cases.  The conditions under which the exception may be thrown
*must* be fully specified in any case.  If only mentioned in throws,
these must be pretty simple.

> as it is simpler to make sure we didn't
> forget anything (using the trick of temporarily changing the base class
> for MathRuntimeException and look at compiler errors).

Now *that* is a good trick.  Thanks for point it out :)

Phil
>
> Big +1
>
> Thanks,
> Luc
>
>>
>> Phil
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
>> For additional commands, e-mail: dev-help@commons.apache.org
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message