We are mixing two things in this thread - how much we care about
backward compatibility and how and when to use interfaces.

I think we need to settle both topics.  I have stated my view, which
is really just to standard Commons policy, on the backward
compatibility issue.  Based on many years experience using,
developing and maintaining libraries here and elsewhere, I agree
with others who have stated that constant incompatible change makes
a library almost worthless for use across a wide range of
applications.  Something just used inside one application or
relatively small development group can be constantly refactored and
productively used; but broadly reusable components need to have
stable APIs.  Incompatible changes have to be well-documented and
introduced in major releases that are relatively few and far
between.  That is essentially how we have operated in Commons for
10+ years now and it is the reason that some suggest that when we do
a major API refactoring of a component we change the package name
and even the component name.

I don't buy the argument that we really *need* to keep making
incompatible API changes in [math] because there are features or
bugs that can't be added in compatible ways.  I have seen only a
tiny handful of these - just one in 2.2.  Luc mentions SVD as a
frustrating problem for us.  The bugs have nothing to do with the
API definition, unless I am missing something basic.  We have
numerical problems.  We need to solve them.  Gilles is right that we
have limited resources.  I would much rather that these resources be
focused on solving the numerical and algorithmic problems involved
in delivering robust and stable mathematical software than endless
arguments about how to refactor the API.  As a user, I would be much
happier with a stable API with a few warts that provides
well-documented, well-tested (because lots of users are using the
*same* core impl) mathematics than a beautiful but unstable API with
buggy implementation code.

Regarding interfaces, I think we are starting to focus on the right
question.  I think we agree that use of interfaces just to separate
interface from implementation in support of the strategy pattern is,
let's just say "deprecated."  When we started [math] back in 2003,
that was not considered bad design.  We went overboard with it,
though, and ran into the problems we have been discussing on this
thread around extensibility.  Most of the bad designs came from my
contributions, so I have to apologize for putting us into this position.

To allow multiple implementations of a fully defined interface, we
seem to have learned in Commons that abstract classes work better. 
I am fine with that principle and will volunteer to start first
suggesting and discussing changes individually and then making
them.  I already started this with RandomData/RandomDataImpl.  We
can continue discussion on that thread about whether we even need an
abstract class in that case.

Other use for interfaces are to
 a) designate behaviors for implementation units that can be
"plugged in" to algorithms (where the interface defines only some of
the behaviors of the class - as in the multiple inheritance
example).  An example of this is the RandomGenerator interface,
which encapsulates the behavior of a low-level source of random data.
 b) encapsulate abstract data types, e.g. Field.

I think we need to keep at least these interfaces, but we should
think long and hard about exactly what they should contain.  Here
again, I think we need to look at each example individually. 
Examples like RealMatrix could be argued to be good "b)" examples or
restrictive handcuffs that should be eliminated.  I think we need to
be very careful with these decisions so that we can aim to really
stabilize the API in 3.0.  I honestly do not think that is an
unrealistic expectation.

Phil
 

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

Reply via email to