...
- A set of guidelines intended to help the Apache Juneau 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.
1 - Interface Types
We identify three distinct categories of interfaces or APIs within a component: external, internal and private.
1.1 - The 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.
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.
1.2 - The 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.
Whenever possible, internal utility classes should be placed in a package with "internal" in the name (e.g. "org.apache.juneau.internal"). Any classes in internal packages are not meant for external consumption.
1.3 - The 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.
Whenever a class, interface or member is considered part of the external or internal interface of a component, it should be clearly indicated as such in the JavaDoc comments or other documentation for the component. (We may want to consider adding custom JavaDoc tags for this purpose.)
2 - 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.
2.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.
...
Developers are encouraged to "upgrade" a release to a stronger type whenever the nature or scope of the change warrants it.
3.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 with the previous release.
3.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.
3.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 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.
3.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.
3.5 - Milestone Releases
Developers may, at their option, offer a milestone preview of any major release. A milestone release is appropriate when part of the overall component is fully functioning and the team wants 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.
4 - Release Numbers
4.1 - Initial Release Number
A component's initial release number is generally 1.0[.0], unless there have been versioned beta releases.
(TODO - Juneau plans on releasing as 6.0?)
4.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.
4.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.
4.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.4, and a developer wished to preview the next major release, the release would be labeled 3.0-M1.
5 - Development States
We identify four possible states: "in development", "beta", "released", and "unsupported".
5.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.
5.2 - Beta State
When a component has made significant progress toward release-quality code, the committers may vote to perform a "beta" release. 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.
...
For example, suppose that the application Foo depends (only) upon features of the commonsjuneau-superwidget core 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 juneau-core 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.
7 - End Notes
- We say "nearly" here 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.
...