On Thu, 2005-10-20 at 06:50 -0400, James Carman wrote:
> What would an abstract class buy us?  Suppose ProxyFactory were an abstract
> class.  In the initial release, it would have some abstract methods to be
> overridden in the subclasses.  Then, I might have some users who decide (for
> some crazy reason) to extend ProxyFactory on their own.  They implement the
> abstract methods and all is good.  Now, suppose that I need to add a method
> to ProxyFactory in the future.  The added method can't be abstract or else
> it would break the binary compatibility.  Therefore, we'd have to provide an
> implementation of the new method.  We'd have a choice here.  We could throw
> an UnsupportedOperationException which would make the method unusable, but
> maintain binary compatibility.  Or, we could provide a default
> implementation which would probably have to be reflection-based anyway to
> avoid unnecessary required dependencies.  I don't really like adding
> unusable methods to my abstract class, so I would rather provide the default
> implementation.  Thus, any new methods would be reflection based.  Why don't
> we just make the base class reflection based in the first place?  

there are no really good solutions to this problem. (or, if there are, i
don't know about them ;) experience has proved though that it's best to
think about it sooner rather than later.

reflection is slow and has wrinkles in some environments and containers.
it's best avoided as a solution.

creating new (logical) interfaces would be an alternative way of
preserving binary compatibility. in some cases, it makes more sense to
create a new interface than add a method to an existing one especially
when semantic compatibility would be broken. the design of proxy
probably makes this a credible strategy. 

> Again, I'm new to this whole "maintaining binary compatibility" thing,
> because thus far I have mostly worked on projects where I control the source
> for the clients of the code that I write.  So, I can go back and fix what I
> broke!  :-)  So, how do you guys usually go about this?  Do you provide the
> default implementation in the base class or throw an exception?

that depends:

the best case (and one that happens a lot) is that the need develops for
optional parameters which were not foreseen when the API was designed.
in this case, it's natural to add a new concrete method that delegates
to the original version. for this case, using an abstract class allows
semantic and binary compatibility to be preserved. using an interface
would mean breaking binary compatibility.

cases requiring the breaking of semantic incompatibility are tougher.
here, novel capabilities which were not foreseen when the API was design
require the addition of new methods. existing implementations may well
be broken by this change whether binary compatibility is preserved or
not. 

it is usually best not to include default implementations in a logical
interface. so, that means creating an empty implementations. indicating
a base implementation containing reasonable defaults (rather than the
abstract class) that implementors are recommended to subclass (so they
can protect themselves against this) is probably a good idea.

there definitely comes a time when it's better to cut your losses and
break compatibility but using an abstract class to model a logical
interface allows this call to be made on a case-by-case basis.

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to