+1
David W. Van Couvering wrote:
Hi, all, here is the vote for the shared components guidelines
following the ASF standard of including the full text of the item
being voted for in the email.
These guidelines will be accessible from the Derby Wiki page at
http://wiki.apache.org/db-derby/SharedComponentVersioningGuidelines
The guidelines as shown here reflect version 29 of this Wiki page.
Version 29 can be directly viewed at
http://wiki.apache.org/db-derby/SharedComponentVersioningGuidelines?action=recall&rev=29
Changes since the last call for a vote can be seen by looking at
http://wiki.apache.org/db-derby/SharedComponentVersioningGuidelines?action=diff&rev1=29&rev2=22
Thanks,
David
== GUIDELINE TEXT TO BE VOTED ON ===
This document describes our guidelines around shared components in
Derby, where a shared component is a collection of one or more
packages that is used across multiple subsystems within Derby. Very
loosely, I would define a "subsystem" as the code contained in one of
the top-level source directories, e.g. engine, client, drda, tools,
etc. As of this writing, the only shared component like this is the
proposed common code component (see [WWW] DERBY-289). Other components
may be defined in the future as needed (for example, perhaps the DRDA
networking code should be separated out as an independent shared
component).
The guidelines for shared components in Derby are based on the [WWW]
Jakarta Runtime Versioning Guidelines. There are some areas that these
guidelines do not cover, however, which we will address here:
1. Mixed Version Support
2. Guidelines for Forward Compatibility
3. Deprecation Guidelines
4. Location and Distribution of Shared Components
5. Documenting Shared Components
6. User Visible Impact and Restrictions
7. Testing Impact
8. Introducing New Shared Components and Shared Packages
MIXED VERSION SUPPORT
Two applications should be able to use one version of the Derby
network client driver and a different version of the Derby embedded
driver within the same Java VM without having to resort to creating
specialized classloaders. This is enabled by supporting forward
compatibility as described below.
GUIDELINES FOR FORWARD COMPATIBILITY
A consumer built against version X.Y of a shared component should work
with version X.Y' of a module where Y' < Y. This is called forward
compatibility.
If the consumer uses new functionality added in version X.Y of the
module, it should degrade to X.Y' level functionality. In the rare
cases where this is not achievable, the consumer should throw an
exception explaining that it requires version X.Y or greater of the
shared component (rather than an obtuse Java exception like
NoSuchMethodException).
Forward compatibility must be guaranteed between patch revisions (from
X.Y.Z to X.Y.Z') and minor revisions (from X.Y to X.Y'). We should
strive for forward compatibility between major releases, but it is not
a guarantee.
The consumer decides it can work with a given version of a shared
component not by looking up its version number and then extrapolating
what features are available, but instead by directly querying the
component to see if the shared component provides the feature or
features it is looking for.
A shared component must provide a class called <ComponentName>Info
that provides a static method called hasFeature. This class should be
at the top level of the package for that component, e.g. the info
class for the common component should be
org.apache.derby.common.CommonInfo.
This method takes a single parameter which is a feature identifier. If
the shared component implementation recognizes the feature identifier,
it returns true, otherwise it returns false. Here is an example
definition and usage using the common component. Assume that a
consumer is making use of a new whizbang feature in the message
utilities in a newer version of the common component which is not
available in older versions.
Here is the old version of the CommonInfo class:
1
2 public static class CommonInfo
3 {
4 public static final int COOL_FEATURE = 1;
5 private static final int MAX_FEATURE = COOL_FEATURE;
6
7 public static boolean hasFeature(int featureId)
8 {
9 return featureID <= MAX_FEATURE;
10 }
11 }
12
Here is the new definition of the CommonInfo class:
1
2 public static class CommonInfo
3 {
4 public static final int COOL_FEATURE = 1;
5 public static final int WHIZBANG_FEATURE = 2;
6 private static final int MAX_FEATURE = WHIZBANG_FEATURE;
7
8 public static boolean hasFeature(int featureId)
9 {
10 return featureID <= MAX_FEATURE;
11 }
12 }
13
The consumer is then built with the new common component and uses the
new CommonInfo class definition:
1
2 if ( CommonInfo.hasFeature(CommonInfo.WHIZBANG_FEATURE) )
3 {
4 // use whizbang feature
5 }
6 else
7 {
8 // use older mechanism
9 }
10
Note that the constant CommonInfo.WHIZBANG_FEATURE is compiled down to
a constant integer, so there will not be runtime errors if the older
version of the component has been loaded.
DEPRECATION GUIDELINES
A method or an interface may be deprecated. This is done using the
@deprecated tag in the method or interface Javadoc. A method or
interface must be available for 2 major releases after it is
deprecated. For example, if it is deprecated in version 8.2, it can be
removed in version 10.0 or greater. An exception to this rule may
occur if it becomes clear that there is still heavy use of this
interface.
LOCATION AND DISTRIBUTION OF SHARED COMPONENTS
All shared components should comprise of one or more packages under
the package org.apache.derby.common (stored in the source tree under
java/common/org/apache/derby/common).
Although it would be conceptually nice to have a separate JAR file for
each shared component, it is a priority for us to keep a very simple
user experience. For this reason, the classes of a shared components
will be merged into the appropriate subset of the existing jar files.
DOCUMENTING SHARED COMPONENTS
We will provide a top-level package.html javadoc under
java/org/apache/derby/common that describes the shared components
guidelines (once they are approved) and lists the available
components. For each shared component we will provide:
* Name of component
* Description of component (its role or intent)
* Packages contained within the component
* The name of the Info class that provides the hasFeature() method
USER VISIBLE IMPACT AND RESTRICTIONS
With these guidelines in place, there will be no visible impact or
restrictions for Derby users.
No visible impact implies the following checkin requirements for any
common code.
* Derby jar files of the same major version can continue to be
mixed within the same JVM classpath without any difference in behavior
from loading these jars in separate classloaders.
* Jar file growth is commensurate with functionality improvement.
* Replacing any jar with a jar of the same major version will not
require any user classpath changes.
The only exception is if for some reason (and this is to be avoided) a
change is made between major revisions that is not compatible, then if
the user is running in a mixed version environment in the same VM, he
or she should attempt to ensure that the jar files from the newer
version are loaded first. If for some reason this is not possible, the
user will need to separate the two versions by using separate
classloaders within the same VM.
TESTING IMPACT
In the first new release after common components are introduced, we
will want to test for compatibility between patch and minor releases
in the following ways:
* Build common component unit tests against the new release and
test against jar files from old releases (backward compatibility tests)
* Build common component unit tests from old releases and test
against jar files from the new release (forward compatibility tests)
Any incompatibilities introduced between patch and minor releases
should be considered a regression. Any incompatibilities between major
releases should be documented.
INTRODUCING NEW SHARED COMPONENTS AND SHARED PACKAGES
When a developer wishes to introduce a new shared component or a new
package within an existing shared component, this should be put up for
a vote. This is to help ensure that what we are sharing makes sense
and does not accidentally paint us into some kind of architectural
corner. Adding new classes or methods to an existing shared package
does not need to be put up for a vote but should be reviewed using the
standard patch review mechanism.