commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From luc.maison...@free.fr
Subject Re: [Math] FunctionEvaluationException in UnivariateRealFunction (Was: Re: svn commit: r1030464 [1/3] - ...)
Date Fri, 05 Nov 2010 11:50:51 GMT
Hi Gilles, and sorry for mistyping your name in my previous message,

----- "Gilles Sadowski" <gilles@harfang.homelinux.org> a écrit :

> Hi.
> 
> > > [...]
> > > > 
> > > > What about new code?  With the current signature and
> documentation
> > > > there is no information on possible exception conditions.  The
> fact
> > > > the method will throw an exception on failure needs to be
> > > expressed.
> > > > 
> > > > [...]
> > > 
> > > The fact is: You don't know whether an exception will be raised
> on
> > > failure.
> > > It depends on the implementation: A user might decide that failure
> is
> > > dealt with by returning "NaN" (or Infinity).
> > > Another user might decide to throw a
> "MathIllegalArgumentException" or
> > > a
> > > subclass thereof or something completely different... :-)
> > > IMHO, the "FunctionEvaluationException" is fairly useless. Its
> only
> > > use I
> > > can see is to wrap "alien" (user-defined) exceptions: Any methods
> in
> > 
> > When this exception was unchecked, it was the primary use of it :
> wrapping
> > exceptions unknown to [math]. Of course, we cannot enforce users to
> use it
> > and even when it was checked users could decide to throw any other
> unchecked
> > exceptions or return NaN. Documenting it is simply a gentle way to
> tell our
> > users this exception is the recommended way to signal errors.
> 
> 
> There are at least 2 different issues:
> 1. What is the recommended behaviour of implementations
> 2. What CM will do when it calls "value" and catches an exception

There is a third issue, and it was a driver for the current architecture.
Some CM algorithms are utilities that are provided by the library that
act on low level user functions and are intended to be called from higher
level user function. They are "sandwiched" between two user levels. Typical
examples are root finding, optimization or ODE integrators.

In this case, the user knows it's own function and the fact it can fail for
some values. When this case occurs, the function throws some kind of exception
so that the algorithm is interrupted. It does not simply return a NaN as this would
simply cause a nightmare in the commons math algorithms. The code compiles only if
the exception was authorized beforehand in the interface (this was the case with the
former architecture an checked exceptions) or if it is an unchecked exception (which is
the case now). Of course, the user could have thrown any other unchecked exception
even in the former architecture. At runtime, the commons-math algorithm does not
catch the exception, neither the checked one before nor the unchecked one now (it may
catch it, wrap it in its own exception and throw the wrapped one again, but I don't
remember any exemple of this behavior in commons-math, only in upper level libraries
I use). So some exception reached higher level user code, and there the user can decide
what to do with it.

If the same development team does develop both user levels, declaring exceptions could
be cumbersome. If different development teams are in charge of the low anf top level,
it is interesting to have a way to convey development guidelines to them via javadoc
or declared throws statements. At least with one generic exception like
FunctionEvaluationException, we provide an hint to developers of the low level function
that it would be wise to stick with this exception type (even if they want to wrap a
NotPositiveException in it for the sake of better relevance). We also provide an hint to
developers of the top level algorithm that calls commons-math that the function they
provide to it and that was provided to them by the other team may throw this exception
and that commons-math simply let it slip upward. So they are aware they should at least
understand when this occurs and be able to act properly.

> 
> For (1) I don't think that it is wise to suggest that any function
> should
> throw "FunctionEvaluationException", because this exception doesn't
> convey
> any information. For example, a function that will compute the
> square-root
> should better throw a more specific "NotPositiveException" (a subclass
> of
> "IllegalArgumentException") when passed a negative argument.

Yes, a more focused exception would be better. It is also possible to
wrap a focused NotPositiveException into a general FunctionEvaluationException
and get the best of both worlds. We cannot enforce it at java level.

> 
> If some part of CM wants to catch a failure (e.g. because the
> computation
> can meaningfully continue, or just to provide a localized message), it
> is
> certainly not safe to catch only "FunctionEvaluationException" since
> indeed
> we cannot enforce that it will be the only exception type to arise.
> Hence, for (2), we will catch *any* "RuntimeException" (and continue,
> or
> throw a "FunctionEvaluationException").

Yes, most of the time I think commons-math will not catch these exceptions
at all.

> It is thus useless and misleading to recommend something that we don't
> care
> about.

Despite I agree with the premisses, I don't agree with this conclusion. We
do care about these exception and we could document them. Simply we cannot
handle them by ourselves and we let them slip upward to the user code calling
our code.

> 
> Thus, neither (1) nor (2) is reason for letting appear the word
> "FunctionEvaluationException" within the interface file.
> 
> To summarize, a "FunctionEvaluationException" class only makes sense,
> IMHO,
> for the localization (of exception messages) requirement: Catch every
> exception and wrap it in a "FunctionEvaluationException".
> [If you agree with this use-case, I'll modify the new
> "FunctionEvaluationException" so that it takes the cause as its
> argument.]
> 
> Please let me know whether you have use cases that would contradict
> the
> above.

Is the user case I exposed above help you understand the rationale behind
the previous architecture ? It is exactly this case that lead me to use
this pattern almost everywhere a commons-math algorithm has to call
user-provided code. The problem first arose in ancient versions of
the mantissa library (some code of which are now in commons-math). I did
not foresee user code could fail when I designed some algorithm (I think it
was about ODE). Then in a real case I had a computation that due to some
underlying library did throw an exception and I could not let it go up
because the interface I had to implement before providing my ODE to an
integrator had no exception at all! So I added a way for user code to signal
some error occurred and did not catch it al all in the integrator, it went
all way up back to user code.

I decided to use checked exception at that time and so documentation was
automatic as the compiler would enforce users to be aware of the exceptions
that may be thrown.

You found that this was cumbersome because some functions may not throw any
exception so the caller of the solver/optimizer/integrator had to deal with
exceptions that would NEVER arise since they are not generated by commons-math
itself and were not generated in some user code.

We decided to switch to unchecked exceptions which in my view is now a good
consensus (you had a hard time convincing me, I know). The case where user
code does need to throw exceptions is still there and it should be handled
gracefully too. The fact we cannot enforce users to use this specific exception
and we cannot prevent them from using another unchecked exception is not a
sufficient reason not to document the way we expect them to behave.

Once again, if the same team or even single developer does both the low and top
levels, he will not care wrapping its MyWonderfulVerySpecificUncheckedException
into a FunctionEvaluationException at low level only to unpack it at top level.
He will simply throw it here and catch it there and all will work seemlessly.
When different, somewhat large teams develop a complex program, sometimes from
different companies in different contracts for the same final user, sharing a
common guideline (it's only a guideline) that FunctionEvaluationException is the
expected way to interrupt commons-math code and go back to user level is a good thing.

Hope this helps,
best regards,
Luc

> 
> > > [...]
> 
> Best, ;-)
> Gilles
> 
> ---------------------------------------------------------------------
> 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