commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles Sadowski <gil...@harfang.homelinux.org>
Subject Re: [Math] FunctionEvaluationException in UnivariateRealFunction
Date Fri, 05 Nov 2010 14:54:57 GMT
Luc,

> > [...]
> > 
> > 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.

I completely agree with the above.

> 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.

>From there I differ because your 3rd case is IMO outside of CM business.
If CM let the exceptions propagate (which I'm all for), why bother with it?
What do we gain in telling developers what they should do? It is clear that
the upper and lower levels teams must communicate (probably through
documentation) but whatever they choose as exception doesn't affect CM at
all. I maintain that it is misleading to let them believe they should stick
to "FunctionEvaluationException"; it's simply not true: this exception or
another will just slip upward, as you said.

> > 
> > 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.

I don't think that it's the best of both, because the wrapping doesn't serve
any purpose.

> We cannot enforce it at java level.

Then, since the users must resort to policy/documentation, it isn't any
easier to stick to the "FunctionEvaluationException" policy than to any
other policy.

> 
> > 
> > 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.

As you've just said: We cannot enforce it. What you describe as "let them
slip upward" I described as "we don't care".
And this is exactly where unchecked exception help: We cannot handle the
exceptions, we let them propagate and... we do not have to litter the code
with "throws" clauses at all the intermediate levels!

> > 
> > 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.

That's fine, and everything will stay the same! You know how the lower level
library behaves, you know that CM won't handle the exceptions thrown by it,
so that you'll catch them in the upper-level code. No need to introduce
un-enforceable (pseudo-)constraints in CM. In this scenario, CM is neutral!

> 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.

[As we discussed and agreed on, the existence of checked exception cannot
prevent any unchecked exceptions to be thrown. So practically we come back
to policy/documentation for your use-case.]

I'd like to stress that automatic documentation is *not* the purpose of
checked exceptions.
As better experts have explained, a checked exception is useful when one
can act on what caused it and retry the computation. Also, this must
probably be done locally (close to source of the problem). [This rules out
your scenario where the exception generated at the lower level but is
handled at the upper level (invalidating all the CM code in-between).]

> 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.

See answer above. [Why do you believe you _expect_ something when you say
"we don't handle the exceptions"?]

> 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.

Exactly! "FunctionEvaluationException" is useless. :-)

> 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.

Interrupting CM code is not an attribute of "FunctionEvaluationException"!
It is the JVM that interrupts the code path when *any* exception is thrown.
That's why we can clean up CM by not implementing/documenting things that
have strictly no influence on CM.

[Sharing is a good thing. But it is a matter of policy.
Moreover, what we cannot enforce within the CM library, we certainly cannot
expect to enforce through telling companies what exceptions their own code
should throw.]

> Hope this helps,

Certainly, but not in the sense which you expected: All you said is
confirmation that I should just delete "FunctionEvaluationException.java".

Maybe I'm missing something obvious to those who'd rather keep a reference
to "FunctionEvaluationException" in the file "UnivariateRealFunction.java".
If so, would someone write a sample code?


Best,
Gilles

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


Mime
View raw message