These guidelines apply right now to Horde itself, the framework packages, IMP, Ingo, Chora, Nag, Mnemo, and Kronolith - all of the applications that have FRAMEWORK_3 branches and were just released. They will apply, in the future, to any application released to work with Horde 3.0 in a FRAMEWORK_3 branch.
Nothing here is set in stone; it's what's been worked out among the core developers for how we want to handle development. The core goals are to make Horde 3 a stable base for a long time, on which we can do frequent releases and speed up development of new features that don't require breaking backwards compatibility. Suggestions and comments are welcome.
Text adapted from http://apr.apache.org/versioning.html.
Conventions: Libraries are the classes of the Horde Framework packages. Applications are the different Horde applications. Modules are libraries, application, and the Horde application itself. APIs are the class interfaces of the libraries and methods of the applications' public APIs.
This document covers how the Horde modules are versioned. Since the Horde modules provide APIs to other applications, it is very important to define a stable API for users of the modules. However, we also need to move the modules forward, technologically. To balance these two needs, a strict policy of versioning is required, which users can rely upon to understand the limitations, restrictions, and the changes that can occur from one release of a Horde module to the next.
Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH. The basic intent is that MAJOR versions are incompatible, large-scale upgrades of the API. MINOR versions retain compatibility with older minor versions, and changes in the PATCH level are perfectly compatible, forwards and backwards.
It is important to note that an application that has not reached 1.0.0 is not subject to the guidelines described in this document. Before a 1.0 release (version 0.x.y), the API can and will be changing freely, without regard to the restrictions detailed below.
We define "compatible" to mean that an application can be used with other modules and will continue to function properly.
Applications that write against a particular version of another module will remain compatible against later versions, until the major number changes. However, if a application uses an API which has become available in a particular minor version, it (obviously) will no longer operate against previous minor versions.
Here are some examples to demonstrate the compatibility:
|Original Version||New Version||Compatible?|
|2.2.3||2.2.4||Yes; Compatibility across patch versions is guaranteed.|
|2.2.3||2.2.1||Yes; Compatibility across patch versions is guaranteed.|
|2.2.3||2.3.1||Yes; Compatibility with later minor versions is guaranteed.|
|2.2.3||2.1.7||No; Compatibility with prior minor versions is not guaranteed.|
|2.2.3||3.0.0||No; Compatibility with different major versions is not guaranteed.|
|2.2.3||1.4.7||No; Compatibility with different major versions is not guaranteed.|
Note: while some of the cells say "no", it is possible that the versions may be compatible, depending very precisely upon the particular APIs used by the applications.
This section details how we will build the code to meet the above requirements and guidelines.
To retain perfect compatibility, a patch release can only change function implementations. Changes to the API, to the signatures of public functions, or to the interpretation of function parameters is not allowed. Effectively, these releases are pure bug fix releases.
Minor releases can introduce new functions and deprecate existing functions.
An application coded against an older minor release will still have all of its functions available with their original signatures. Once an application begins to use a new function, however, they will be unable to work against older minor versions.
It is tempting to say that introducing new functions might create incompatibility across minor releases. If an application takes advantage of an API that was introduced in version 2.3 of a module, then it is not going to work against version 2.2. However, we have stated that an application created against version 2.2 will continue to work for all 2.x releases. Thus, an application that states "requires 2.3 or later" is perfectly acceptable -- the administrator simply upgrades the installed prerequisite to 2.3. This is a safe operation and will not break any other application that was using the 2.2 version.
In other words, yes an incompatibility arises by mandating that a specific version needs to be installed. But in practice, this will not be a problem since upgrading to newer versions is always safe.
This gets a bit trickier. The original function must remain available at the API level so that an application created against a minor version will continue to work with later minor versions. Further, if a application is designed to work with an earlier minor version, then we don't want to suddenly change the requirements for that application.
The new, alternate function can be made available in the API and applications can choose to use it (and become dependent upon the minor release where the function appears).
Since a function must remain available for applications coded against a previous minor release, it is only possible to "deprecate" a function. It cannot be removed from the APIs (so that compatibility is retained).
If you deprecate a function in a module, please mark it as such in the function documentation, using the phpdoc "@deprecated" tag. Deprecated functions can only be removed in major releases.
Finally, if you are deprecating a function so that you can change the name of the function, please use the method described above under "Replacing functions", so that projects which use a module can retain compatibility.
Note that all deprecated functions will be removed at the next major version bump.
Any kind of change can be made during a major version release. Particular types of changes that might occur: