to distinguish between changes that will break them by changing an API , and changes
that are internal only.
The OSG i Alliance recommends a scheme called semantic versioning. It's simple,
but it carries much more information about what's changing than normal versions.
Every version consists of four parts: major, minor, micro, and qualifier (M.m.µ.q). A
change to the major part of a version number—for example, changing 2.5.0 to 3.0.0—
indicates that the code change isn't backward compatible. Removing a method or
changing its argument types are examples of this kind of breaking change. A change
to the minor part indicates a change that is backwards compatible for a consumer of
an API , but not implementation providers. For example, the minor version should be
incremented if a method is added to an interface. If a change doesn't affect the exter-
nals, it should be indicated by a change to the micro version. Such a change could be
a bug fix, or a performance improvement, or even the removal of methods from
classes that are internal to a bundle. Having a strong division between bundle inter-
nals and bundle externals means the internals can be changed dramatically without
anything other than the micro version needing to change. Finally, the qualifier is used
to add extra information like a build date.
Guarantees of compatibility
One of the benefits provided by the semantic versioning scheme is a guarantee of
compatibility. A module will be bytecode compatible with any versions of its depen-
dencies where only the minor or micro version has changed.
Backward compatibility is no guarantee of forward compatibility, and so modules
should not try to run with dependencies with minor versions lower than the ones they
were compiled against.
Coexistence of implementations
The other major benefit provided by versioning is that it allows different versions of a
module to coexist in the same system. If the modules weren't versioned, there would
be no way of tagging them as different and isolating them from one another. With ver-
sioned modules, OSG i classloading allows each module to use the version of its depen-
dencies that is most appropriate (see figure A.1).
When importing a package, it's always a good idea to add version constraints. Usu-
ally, the minimum is the version currently being used, and the maximum is the next
major increment (non-inclusive). It's not sensible to accept the next major increment,
because you know (because of semantic versioning) that this version will have breaking
changes in it. Minor version increments can be safely accepted, and they may bring bug
fixes or other improvements. The following import statement will resolve against any
version of the food.nice package above or equal to 1.4.3, but less than 2.0.0 (which
would contain a breaking change):
Import-Package: food.nice;version="[1.4.3, 2.0.0)"
Search WWH ::