[RFC_v3] Handling Backwards Compatibility in PEAR [hopefully the final draft]
| From: | Greg Beaver | Date: | Wed, 24 Sep 2003 17:36:37 +0000 |
| Subject: | [RFC_v3] Handling Backwards Compatibility in PEAR [hopefully the final draft] | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-21935@lists.php.net to get a copy of this message | ||
[RFC3] Handling Backwards Compatibility in PEAR
Sept. 24, 2003
Greg Beaver , Lukas Smith
Alexey Borzov, contributor [Announcing API Changes]
The Problem:
------------
PEAR does not have a system in place to handle backwards compatibility issues.
definitions:
BC: "Backwards Compatibility" means programs that rely upon a package will still work when the package is upgraded. It is assumed that the programs using the package only use elements of the API, and do not use any private elements. This obviously means that new functionality may be added as long as it doesn’t interfere with existing functionality.
API: "Application Program Interface" is the connection between a package and the programs that use it. This includes class and method names, parameters that are passed to methods, and constant names, or any other publicly accessible area of a program. Elements explicitly marked as private data/methods are excluded from this definition.
The Solution:
------------
The API of a PEAR package may only break BC if:
1) The packages is in the preparation phase to a new major version number
2) A new major stable release is made
It is up to the lead developers to determine whether BC needs to be
broken. It is highly encouraged to carefully select the API before
version 1.0 so that changes to the API that break BC will not be
necessary.
Versioning:
-----------
The first stable release of a package is version 1.0. If a package
breaks BC at all, the version shall bump to the next whole number, 2.0.
Developers should also consider bumping the major version number if they
make a major rewrite that maintains BC because there might be hidden BC
breaks as follows:
1. changes in performance behavior
2. changes in code maturity
3. compatibility to user patches
When the major version is bumped a new package is created with the same
name and a postfix with the new major version number in order to make it
possible to have two different major versions of a package in use within
a single script. This also means that all classes, functions, globals
and defines (everything that is accessible through the global namespace)
need to get this postfix. The new package will however will continue in
the version progress of its predecessor.
The postfix format shall be
_vX
where X is the major version number. The PEAR directory naming conventions shall remain the same, but files in newer versions will follow this format:
Foo.vX.php contains class Foo_vX
Foo/vX/support.php contains class Foo_vX_support
Version 1.x of the Foo package will have this structure
Foo.php contains class Foo
Foo/support.php contains class Foo_support
This naming convention allows the packages to co-exist while the Foo package is deprecated:
Foo.php
Foo.vX.php
Foo/support.php
Foo/vX/support.php
Example:
-------
Lifecycle of package Foo
1) release Foo-0.1 - devel (initial version)
2) release Foo-0.2 - devel (BC break allowed)
..
3) release Foo-0.9a - alpha (BC break allowed - but discouraged)
4) release Foo-1.0b1 - beta (BC break allowed - but heavily discouraged)
5) release Foo-1.0 - stable (BC break allowed - but heavily discouraged)
6) release Foo-1.0.1 - stable (BC is not allowed)
7) release Foo-1.1.0 - stable (BC is not allowed)
...
8) release Foo-1.1dev1 - devel (BC is not allowed)
8) release Foo-1.1b1 - beta (BC is not allowed)
9) release Foo-1.1 - stable (BC is not allowed)
..
10) release Foo-1.2 - stable (BC is not allowed)
11) release Foo_v2-2.0dev1 - devel (BC is allowed)
12) release Foo_v2-2.0a1 - alpha (BC is allowed - but discouraged)
13) release Foo_v2-2.0b1 - beta (BC is allowed - but heavily discouraged)
14) release Foo_v2-2.0 - stable (BC is allowed - but heavily discouraged)
15) release Foo_v2-2.0.1 - stable (BC is not allowed)
With release 11) Foo becomes deprecated in favor of Foo_v2 and only bug fix releases will
be made that will not increase the major version number.
Announcing API changes:
-----------------------
If there is a need to remove a public or protected method, then
1) If it is possible to implement the same functionality in other methods then such functionality should be added and the method should be marked deprecated in major release. This means that the method can be removed in any of the following major releases.
2) If it is not possible to implement the same functionality or if the method is removed due to API simplification then the package should enter beta stage before the next major release.
Reasoning: API breaks will not happen without due warning. If you do not use deprecated methods and the next major version comes out, you can safely upgrade to it. If the package you depend upon enters alpha/beta stage, then you should test for compatibility before upgrading.
Complete API change:
--------------------
If a package is stable, and is rewritten with a completely different API that may need to temporarily co-exist with the older version, then the following solution should be used:
Imagine package Foo version 1.6 is the latest stable release of Foo. The next release with a complete API rewrite shall be package Foo_v2 version 2.0.
At this point, package Foo will automatically be considered a deprecated package. Foo_v2 will be intended to eventually replace Foo in all installations, and all development of new features on Foo will freeze permanently. New development will continue in package Foo_v2.
In addition, the name of all paths and classes shall change to reflect this.
file Foo.php:
<?php
class Foo {
}
?>
becomes
file Foo.v2.php:
class Foo_v2 {
}
Here's a scenario that may illustrate the need for specifying 1 package is the main package:
Package FOO version 1.7 is out, package FOO_v2 version 2.0 is released. You want to maintain both packages. Say you decide to rewrite a large portion of the core of FOO. This would then suggest you bump the major version to 2.0. Now we have FOO version 2.0, and FOO_v2 version 2.0. This is unacceptable ambiguity.
Once FOO_v2 is released, all major development on FOO 1.x is frozen - only bugfixes and minor feature enhancements will be allowed. So, FOO 1.5 or FOO 1.99 or FOO 1.999 is allowed, but never FOO 2.0 if the FOO_v2 package exists - it is expected that people will switch their code to FOO_v2 if the FOO package doesn't do what is needed in its current form.
Changes to the PEAR Installer:
------------------------------
The PEAR Installer will not install a version of a package with a major version number greater than the current major version without the --force option. If a newer minor version of the current major version exists, that will be installed. Example:
Package Foo's latest versions are 1.7 and 2.0
$ pear install Foo-1.6
Foo version 1.6 installed successfully
$ pear upgrade Foo
Foo version 1.7 installed successfully
$ pear upgrade Foo-2.0
version 2.0 does not exist of package Foo, use pear install Foo_v2 for version 2.0 of package Foo
$ pear install Foo_v2
Install of Foo_v2 version 2.0 successful
The PEAR Installer will also add the revert command, which will restore a previous installation
$ pear install Foo-1.6
Foo version 1.6 installed successfully
$ php -q usesFoo.php
Mmmmmmm, Foo :)
$ pear upgrade Foo
Foo version 1.7 installed successfully
$ php -q usesFoo.php
Error: something didn't work right
$ pear revert Foo
Reverting to version 1.6 of Foo
$ php -q usesFoo.php
Mmmmmmm, Foo :)
$
The same changes apply to the automatic upgrading of dependencies through the --alldeps and --onlyreqdeps command-line switches.
Infractions:
------------
If a package is released that breaks BC and isn't a major version number increase, the PEAR Group may at their discretion remove the release and require it to be a new major version number. A public announcement as well as a personal email to the lead maintainer(s) of the package shall be sent explaining the reasoning.