Version numbers and dependency specifications are best expressed at the level of the distro (i.e. the atomic unit of installation) rather than at the level of the module.
CPAN authors can emulate distro-level versioning by unifying version numbers across all subcomponents and by treating the removal of a module from a distro as a backwards compatibility break.
A number of distributions on CPAN provide multiple modules with disparate $VERSION numbers. Take URI 1.60:
URI: 1.60
URI::Escape: 3.31
URI::Heuristic: 4.20
URI::Split:
URI::URL: 5.04
...
The CPAN toolchain supports expressing dependencies at the level of individual modules...
requires:
URI::Escape: 3.31
... though it is common to use only the primary module in the distro as a proxy for all the others:
requires:
URI: 1.60 # may be a proxy for URI::Escape 3.31
In theory, it is safest for downstream users to express all module dependencies individually, because individual dependency specs will continue to resolve properly if a module moves to a different distribution -- for example, if URI::Escape were to be broken out of URI.
However, there are numerous distributions out there which are structured as large collections of small modules, and for which it would be tedious and error-prone to specify each constituent dependency seperately. The existence of such distributions renders strict per-module dependency specification impractical.
The only safe assumption for an author to make is that some fraction of the user base has listed the primary module of a distro as a dependency when they really want a different module within the distro. Users in this category are going to get burnt when their desired module gets removed. Therefore, removing a module from a distro must be classified as a compatibility break.
Say that URI::Escape makes a major version increment, but URI does not:
URI 1.60 ... 1.61 URI::Escape 3.31 ... 4.00
The distribution's version number only moves from 1.60 to 1.61 because is tied to the URI module -- URI::Escape is only along for the ride.
Unfortunately, this minor version increment fails to communicate to downstream users that a potentially backwards-incompatible major version break has occurred.
Authors can still do evil things in the context of per-distro packaging, such as breaking back compat within a subcomponent without incrementing the distro's major version number. However, it is more obvious that you're doing something wrong because the distro's version number unambiguously represents everything together.
Removal of a subcomponent is likewise an unambiguous compatibility break -- that is, unless the subcompoment gets broken out into a new distro which gets added to the original distro's dependency chain as a mandatory prerequisite.
The downside is that we must assume that some fraction of the user base will attempt to specify per-module dependencies and will not get their desired behavior.Fortunately, it is possible to emulate distro-level versioning while still supporting downstream users who make per-module dependency specifications:
1 Update: "Suggestions" just sounds a little more humble the morning after. :)
|
|---|