rwaldhoff 01/08/30 11:29:37
Added: . VERSIONING-GUIDELINES.txt
Log:
initial draft
Revision Changes Path
1.1 jakarta-commons/VERSIONING-GUIDELINES.txt
Index: VERSIONING-GUIDELINES.txt
===================================================================
$Id: VERSIONING-GUIDELINES.txt,v 1.1 2001/08/30 18:29:37 rwaldhoff Exp $
-----------------------------------------------------------
This is a draft set of recommendations, adapted from a
similar document in the Jakarta-Taglibs project. It is not
binding in any way, although Jakarta-Commons components
may choose to adhere to these guidelines.
-----------------------------------------------------------
VERSIONING GUIDELINES
---------------------
TABLE OF CONTENTS
-----------------
1 OVERVIEW
2 TYPES OF INTERFACE
2.1 "EXTERNAL" INTERFACE
2.2 "INTERNAL" INTERFACE
2.3 "PRIVATE" INTERFACE
3 TYPES OF CHANGE
3.1 "FULLY-COMPATIBLE" CHANGES
3.2 "INTERFACE-COMPATIBLE" CHANGES
3.3 "EXTERNAL-INTERFACE-COMPATIBLE" CHANGES
3.4 "INCOMPATIBLE" CHANGES
4 RELEASE TYPES
4.1 "MAJOR" RELEASES
4.2 "MINOR" RELEASES
4.3 "POINT" RELEASES
4.4 "BETA" RELEASES
4.5 "MILESTONE" RELEASES
5 RELEASE NUMBERS
5.1 INITIAL RELEASE NUMBER
5.2 DISSECTING THE RELEASE NUMBER
5.3 "BETA" RELEASE NUMBERS
5.4 "MILESTONE" RELEASE NUMBERS
6 DEVELOPMENT STATES
6.1 "IN DEVELOPMENT" STATE
6.2 "BETA" STATE
6.3 "RELEASED" STATE
6.4 "UNSUPPORTED" STATE
7 COMMENTARY
CONTENTS
--------
1 OVERVIEW
This document provides:
* a set of guidelines intended to help the Jakarta-Commons
team balance the need to provide a stable interface to
clients with the growth and evolution of components over
time
* a language for describing the changes to a component
and the types of incompatibilities such changes may
create
* a protocol for communicating those changes and
incompatibilities to users and developers.
2 INTERFACE TYPES
We identify two distinct categories of interfaces or APIs
within a component: "external" and "internal".
2.1 "EXTERNAL" INTERFACE
The "external" interface of component is composed of the
public-facing classes, interfaces, methods and attributes
provided by the component--those that are likely to be
used by clients to the component.
For obvious reasons, we try to avoid or at least
acknowledge changes to the external interface of a
component.
The external interface of a component _may_ correspond to
the public scope classes and members, but this is not
always the case. For example, a protected method of a class
designed to be extended by the clients of a component may
be deemed part of the external interface.
If a class, interface or member is considered part of the
external interface of the component, it should be clearly
indicated as such in the JavaDoc comments or other
documentation for the component. (We may want to consider
adding a custom JavaDoc tag for this purpose.)
2.2 "INTERNAL" INTERFACE
The "internal" interface of a component is composed of the
classes, methods and attributes that are primarily or
exclusively intended for use by the component
implementation itself. Clients to the component are
unlikely to use or be concerned with the internal
interface.
The internal interface of a component _may_ correspond to
the package and private scope classes and members of the
component, but this is not always the case. For example,
a component implementation may be split over multiple
packages and hence require protected scope members, or
may, for design reasons, include an interface intended
primarily for internal use.
If a class, interface or member is considered part of the
internal interface of the component, it should be clearly
indicated as such in the JavaDoc comments or other
documentation for the component. (We may want to consider
adding a custom JavaDoc tag for this purpose.)
2.3 "PRIVATE" INTERFACE
The "private" interface of a component is just that--the set
of classes, methods and attributes that have package or
private scope and hence cannot be used by external clients
by virtue of the Java Language Specification.
3 TYPES OF CHANGE
We can categorize the changes to a component according to
the degree to which these changes are compatible with
previous releases of the component. We define three
such categories: "fully-compatible",
"interface-compatible", and "external-interface-compatible".
3.1 "FULLY-COMPATIBLE" CHANGES
Release B is said to be "fully-compatible" with Release A
if B can simply replace A in (nearly*) all circumstances
and deployments without changing the client code or
configuration, and without changing the semantics of any
public or protected member.
Examples of fully-compatible changes include:
* adding a non-abstract method to a class
* adding a class or interface to a component
* changing a member from private to protected
* changing a private attribute to a private method
* changing an implementation such that a given external
library is no longer needed by the component
* changing a component in order to fix a defect (a
deviation from the documented or reasonably expected
behavior), assuming no other incompatibilities are
introduced
Note that not every non-fully-compatible change will cause
compilation or readily apparent run-time problems.
Examples of changes which are not fully-compatible include:
* a release that no longer supports the same set of JREs,
or that requires new libraries to be added to the
classpath
* changing a public or protected method signature
* changing the default value of an attribute in a
behaviour changing way
* removing a class, interface, method or attribute from
either the internal or external interface of the
component
Generally speaking, an fully-compatible change will at
most change the private interface of a component, or simply
add classes, methods and attributes whose use is optional
to both internal and external interface clients.
3.2 "INTERFACE-COMPATIBLE" CHANGES
Release B is said to be "interface-compatible" with Release
A if (nearly*) all clients C that can be compiled with A in
the classpath can also be compiled with B in the classpath,
without changing the semantics of any public or protected
member. A configuration or classpath change may be
required.
Examples of interface-compatible changes include:
* all fully-compatible changes
* changing a component such that it now depends upon an
additional external library or configuration file
Examples of changes which are not interface-compatible
include:
* changing a public or protected method signature
* changing the default value of an attribute in a
behaviour changing way
* removing a class, interface, method or attribute from
either the internal or external interface of the
component
Generally speaking, an interface-compatible change will at
most change the private interface of a component, or simply
add classes, methods and attributes whose use is optional
to both internal and external interface clients.
3.3 "EXTERNAL-INTERFACE-COMPATIBLE" CHANGES
Release B is said to be "external-interface-compatible"
with Release A if (nearly) all clients that depend only
on the external interface of a component and that can be
compiled with A in the classpath can also be compiled with
B in the classpath, without changing the semantics of any
member in the external interface. A configuration or
classpath change may be required.
Examples of external-interface-compatible changes include:
* all interface-compatible changes
* removing a class, interface, method or attribute from
the internal interface of the component
* a change to the internal or private interface of a
component that requires a change in configuration
settings or in the external libraries required to
use the component
* changes to the internal or private interface of a
component without impacting the external interface
Examples of changes which are not external-interface-
compatible include:
* changing the method signature of any method that is
part of the external interface of the component
* changing the default value of any attribute that is
part of the external interface of the component in a
behaviour changing way
* removing a class, interface, method or attribute from
external interface of the component
Generally speaking, external-interface-compatible changes
correspond to changes to at most the internal interface of
the component or the addition of optional classes,
interfaces or members to the external interface.
[Note *] - I say "nearly" in the above since there are rare
or unusual circumstances in which changes that are usually
"safe" may cause problems for a small number of users.
For example, adding a new method to a component class
shouldn't in general cause problems for any clients. But it
may cause problems for some clients who've extended that
class and already added a method with the same signature in
their subclass.
4 RELEASE TYPES
We identify five types of releases: "Major", "Minor",
"Point", and "Beta".
Developers are encouraged to "upgrade" a release to a
stronger type whenever the nature or scope of the change
warrants it.
4.1 "MAJOR" RELEASES
Major releases signify significant changes to a component.
Developers _may_ perform a major release if there have been
substantial improvements to the component. Developers
_must_ perform a major release whenever the new release
is not at least interface-compatible the previous release.
4.2 "MINOR" RELEASES
Minor releases signify enhancements to a component that do
not necessitate a major release. Developers _may_ perform a
minor release if the release is at least
external-interface-compatible with the previous release.
In other words, whenever a client depends upon at most
the external interface of a component with a given minor
release, it will work with all subsequent minor releases
within that major release.
4.3 "POINT" RELEASES
A point release typically involves simple bug fixes or
optimizations that do not introduce new features.
Developers _may_ perform a point release if the release
is at least (internal) interface-compatible with the
previous release.
In other words, whenever a client depends upon a component
with a given point release, it will work with all
subsequent point releases within that minor release.
4.4 "BETA" RELEASES
Developers may, at their option, perform a beta preview of
any major, minor or point release. Beta releases may be
performed for a variety of purposes such as:
* Showcasing new, untested features
* Providing early corrections of critical bugs
* Generating a stable version before large-scale changes
While every effort should be made to ensure the quality of
released code, "beta" releases are essentially provided
as-is with no guarantees of stability or maintenance.
4.5 "MILESTONE" RELEASES
Developers may, at their option, offer a milestone
preview of any major release. A milestone release is
appropriate when you have part of the overall component
fully functioning and you want to make it more widely
available for testing. Those features implemented and those
remaining to be implemented should be clearly defined and
documented.
While every effort should be made to ensure the quality of
released code, "milestone" releases are essentially
provided as-is with no guarantees of stability or
maintenance.
5 RELEASE NUMBERS
5.1 INITIAL RELEASE NUMBER
A component's initial release number is generally
1.0[.0], unless there have been versioned beta releases.
5.2 DISSECTING THE RELEASE NUMBER
A release number is comprised of 3 components: the major
release number, the minor release number, and an optional
point release number. Here is a sample release number:
2.0.4
and it can be broken into three parts:
major release # = 2
minor release # = 0
point release # = 4
The next release of this component would increment the
appropriate part of the release number, depending on the
type of release (major, minor, or point). For example, a
subsequent minor release would be version 2.1, or a
subsequent major release would be 3.0.
Note that release numbers are composed of three _integers_,
not three _digits_. Hence if the current release is
3.9.4, the next minor release is 3.10.0.
5.3 "BETA" RELEASE NUMBERS
Beta releases are denoted by adding
"B<beta version number>" after the release number. For
example, if the current release version is 2.0.4, and a
developer wished to preview the next major release, the
release would be labeled 3.0-B1.
5.4 "MILESTONE" RELEASE NUMBERS
Milestone releases are denoted by adding
"M<milestone version number>" after the release number. For
example, if the current release version is 2.0, and the
developer wished to preview the next major release, the
release would be labeled 3.0-M1.
6 DEVELOPMENT STATES
We identify four possible states: "in development", "beta",
"released", and "unsupported".
6.1 "IN DEVELOPMENT" STATE
When a component is "in development", it is new and still
relatively unstable. Typically components in this state
do not have any binary releases available beyond the
nightly builds. Users should be made aware that this
component may change its functionality or interface before
a stable release is achieved. A "milestone" release may
be made while the component is still "in development" to
make the features currently implemented more widely
available for testing in a more stable test version.
6.2 "BETA" STATE
When a component has made significant progress toward
release-quality code, the committers may vote to perform
a "beta" release (see section 1.4). At this point, the
component state will change from "in development" to
"beta". The component will remain in this state until
it is ready for its first major release.
Note that developers may skip vote to skip the "beta" state
and go directly to "released", if the component is
sufficiently stable.
6.3 "RELEASED" STATE
When a new tag library is finally production-quality, the
developers will vote to perform the first major release
(see section 1.1). At this point, the component status
will be changed from "beta" to "released". In the future
this component will always be considered to be in the
"released" state, even when new releases are initiate.
The only exception is in the case of "unsupported"
components.
6.4 "UNSUPPORTED" STATE
Under rare circumstances, committers may vote to make a
component "unsupported", if there are no resources to
maintain the library or if it has been completely
supplanted by another component. Only "released"
components may become "unsupported"; components in other
states will simply be terminated after a brief warning
period.
7 COMMENTARY
Using this approach it is possible to very precisely and
concisely define the dependencies between a component and
its clients.
For example, suppose that the application Foo depends
(only) upon features of the commons-superwidget component
that are part of the external interface in release 2.3.0.
Then the maintainers of Foo can state with a high degree of
certainty that Foo will work with any 2.x release of
superwidget (x >= 3).
Similarly, suppose the application Bar depends upon
features of superwidget that were part of the internal
interface of release 2.3.0. Then the maintainers of Bar
can state with a high degree of certainty that Bar will
work with any 2.3.x release of superwidget. Only once 2.4
(or 3.0) is released, will Bar's developers have to
re-evaluate.