Hello.

> >>>
> >>> in ConjugateGradient, I get the following error
> >>>
> >>> "Exception NonPositiveDefiniteOperatorException is not compatible with
> >>> throws clause in
> >>> PreconditionedIterativeLinearSolver.solveInPlace(RealLinearOperator,
> >>> RealLinearOperator, RealVector, RealVector)"
> >>>
> >>> This comes from the fact that general iterative solvers do not require
> >>> positive definite operators (therefore, no
> >>> "throws NonPositiveDefiniteOperatorException" clause in the signature of
> >>> PreconditionedIterativeLinearSolver.solveInPlace), while conjugate
> >>> gradient does.
> >>>
> >>> Do I need to add the "throws NonPositiveDefiniteOperatorException"
> >>> clause in the signature of
> >>> PreconditionedIterativeLinearSolver.solveInPlace as well?
> >>
> >> I think so, as users may use a ConjugateGradient and store it in a
> >> variable declared with the base class only. However, I don't know if
> >> adding an unchecked exception to the signature of an interface is a
> >> compatible change or not.
> >>
> >> Luc
> >>
> > clirr does not seem to be complaining, so I'll do as you say. Here is
> > what I'm planning to add to the javadoc of the mother abstract class.
> > What do you think?
> > 
> >      * @throws NonPositiveDefiniteOperatorException if {@code a} or {@code 
> > m}
> >      * is not positive definite (required by some iterative solvers)
> 
> Perfect!

I don't agree on the principle that base classes/interfaces should be aware
of the detailed requirements of their implementations.
We can foresee that subclasses might need to throw _some_ kind of exception
when something (yet unknown at the time of the interface design) goes wrong.
But base classes (or interfaces) should not have to change when a new class
extends (or implements) it.

For cases like the above, we must create a parent exception (or use an
existing one if it is appropriate) in order to convey that subclasses
_might_ throw exceptions that inherit from that one.
It this particular case, it seems that operators that are not positive
definite are illegal for method "solveInPlace", hence we conclude (not
surprisingly) that "MathIllegalArgumentException" can be thrown from classes
that implement "RealLinearOperator.solveInPlace".

In fact, this is even too much of a "guessing" work. And this where a single
root can be used to clearly advertize that, by design, CM is supposed to
throw only (subclasses of) "MathRunimeException". _That_ exception, and
_nothing_ else should really be inserted in the "throws" clause of upper
level base classes and interfaces.

Referring to the above example, it is the duty of the user of CM to read the
documentation of the (concrete) classes he uses if he wants to know which
subclass of "MathRuntimeException" may actually be thrown; it is not enough
to read the documentation of the interface!
To be clear, CM will become a total clutter if upper levels attempt to
report everything all the way down. This is in blatant contradiction with
the principle (or rule, or best practice) of encapsulation.


Best regards,
Gilles

> > [...]

P.S. Practically, at this point, I propose to not touch interfaces or base
     classes, but only add the "throws" clauses where the methods actually
     throw the exceptions, and in some cases, one level up (where it is
     still obvious that a particular condition is required).
     Of course, that makes it impossible to test the "switch to checked
     exception" as the work is in progress. For this, let's wait until all
     the first pass has been completed, then we can see what is missing,
     and decide while seeing the picture.

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

Reply via email to