cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <blorit...@apache.org>
Subject [Proposal] Deprecation Policy
Date Thu, 13 Dec 2001 14:49:09 GMT
It has become painfully clear to me that the Cocoon team does not practice
proper API migration techniques.  This is evident in the fact that some
classes were missing that used to be in Cocoon as recently as a couple
months ago.

This is _very_ frustrating, because a project that I left that long ago
no longer works with the current Cocoon.  Now I have to go through and
see what needs to change to make it work again.  This should not be.

As Release Manager for the Avalon team, I have learned alot about providing
a stable API.  This means that not only do you need to provide deprecation
warnings, but you have to maintain functionality as long as possible for
the deprecated function.  Giving any team less than six *months* is simply
not an option.  In fact, we discovered that we had to place some classes
back in LogKit when we hit the six month mark.  It turns out that six months
is not even enough time.

So, for the Cocoon team, I propose that we adopt a deprecation practice
here and now, before we alienate users due to backward incompatible changes.
In fact, as soon as the project was in Beta, we *should* have been using
proper deprecation techniques.

The types of changes that are _not_ backwards compatible include: changing
method signatures, adding new methods to an interface or abstract class,
changing the name of a Class, and changing the core behavior of a class.

Here is a list of actions for the different deprecation types:

* Changing Method Signatures.  The vast majority of these are simply altering
   the number of parameters passed.  In those cases, merely add the "@deprecated"
   flag to the javadoc comment area (yes, the compiler reads these).  The
   implementation should merely call the new function with any default values
   that are needed.

* Adding new methods to an interface or abstract class.  This is only an issue
   when there is no implementation of that method.  If you add a method to an
   abstract class that has an implementation to it, you will be ok.  However,
   interfaces never allow an implementation.  If at all possible, *do*not*do*it.
   Look for other ways to provide the functionality you need.  The Avalon team
   ran accross a situation where this was simply not possible: adding the Logger
   abstraction to Framework.  In this case, we deprecated the old Loggable interface,
   pointing users to the new LogEnabled interface.

* Changing the name of a class.  Sometimes this is done because the class was
   mispelled (like the DijkstraSemaphore class in Excalibur).  In these cases,
   we changed the name of the class, and created a new class with the old name
   that merely extended the new class.

   class DijkstraSemaphore { /* implementation */ }
   /** @deprecated use DijkstraSemaphore instead */
   class DjikstraSemaphore extends DijkstraSemaphore {}

   This works wonderfully in most cases as the old class name still gets bug
   fixes but we only have to maintain the correct class.

   Sometimes this is done because the class is being repurposed.  I am sorry, but
   in this case you are going to have to maintain two different classes.  Do deprecate
   the old one, but you still have to maintain it for as long as it remains part
   of Cocoon.

* Changing the behavior of a class.  An example of this would be the added namespace
   support for Configurations.  The previous version of Framework only allowed the
   Configuration name to be keyed off of the raw name for an element.  In other words,
   if the configuration had namespaces declared for a component, you would see
   "map:parameter" as the name of the Configuration element.  With added namespace
   support, there is a new method called "getNamespace()" which returns the string
   representation of the namespace.  The name of the Configuration element is now
   simply "parameter" with a namespace that "map:" was mapped to.  In the end this
   is more correct--but what about all those applications that would break because
   the name of the Configuration has changed?

   The Avalon team fixed this by providing a different Configuration reader.  There
   is the SAXConfigurationBuilder, and the NamespacedSAXConfigurationBuilder.  The
   difference between the two are names of the Configuration element built.  At this
   time, neither implementation is deprecated--but as needs change that may change.

   In this case you have to think long and hard about the consequences of such a move.
   You want to minimize the impact--but if it is best in the long run, do provide a
   deprecation warning.

Lastly I also want to have a note about the minimal set of Components that are
required to make Cocoon run.  I am not against adding functionality.  However,
if the required set of Components changes from release to release, you are going
to make a lot of enemies.  Stick with a core set, and if it changes, you have to
provide meaningful messages in the log files, as well as announce it in the release.
The *exact* changes to the cocoon.xconf should be documented.  If at all possible,
please provide a kind of deprecation in your config files.  You may not be able to
declare them programatically, but you can declare them in the logs.  This is the
approach I used for the DataSourceComponent.  The JdbcDataSource has had it's
configuration change slightly, but still supports the old method.  It does send
a deprecation warning to the logs so that you know it is not the correct way of
configuring it.

-- 

"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin


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


Mime
View raw message