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
Date Fri, 05 Nov 2010 16:57:36 GMT
Hi Gilles,

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

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

Fine, thanks.

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

Because we suggest users should use these exceptions. These are guidelines.

> 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

We help build a common infrastructure or guidelines on which they can rely.
Sometime, the teams do not even know each other, it may be impossible for them
to communicate. But team LowA could say "hey, the CM guys suggest me to use
a FunctionEvaluationException for my error, let's do that" and then team
High would say "hey, it's good, on all our dependencies all teams LowA, lowB,
... and lowZ all choosed the recommended FunctionEvaluationException, it is
much simpler for us to use their libraries.

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

Yes, and it is sad but unavoidable. Not a reason to not try to provide
some guidelines. Some people say managing programmers is like herding cats,
managing exceptions is the same.

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

It's true when everybody knows whats going on. It's false in a multi-team
environment where its added value is to simplify work for team High as it
can hope a catch FunctionEvaluationException will work in most situations
as long as all teams Low did not simply ignore documentation. If the
documentation does not exist at all, they are enforced to ignore it and
then it enforce making work for team High harder.

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

It's not easy, for sure. But it helps. Documenting always helps.
To focus again on the core problem, what we are talking about here is
only documentation.

> 
> > 
> > > 
> > > 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 where we don't agree. We care of it, even if we let these
exceptions occur.

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

We don't speak about throws clause, we speak about javadoc. We speak
about guidelines. We speak about recommendations. We speak about non-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.
> 
> 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!

Yes, and this as already been accepted some times ago. And once again,
we don't try to introduce constraints, only documentation and hints for
users (both team Low and team High).

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

Yes. This is exactly my point! I want documentation.

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

It is useless in this use case. It is useful in other use cases.

> 
> > 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 was exactly the purpose of FunctionEvauationException.

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

No. Even if you don't use it, it helps other people leverage their code
when they use several underlying providers for some pluggable functions
implementations. There are use case when this exception simplifies code,
please keep it for the sake of these people ease of mind.

cheers,
Luc

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

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


Mime
View raw message