Dependency Management & Versioning

As you can see from my previous rant on dependency management, one aspect that will rear it’s head in any dependency management solution is that of version numbers.

Branding

One of the things that’s not immediately obvious is that version numbers mean different things to different people. In particular, the version number you, the user, read is not necessarily the version number that means anything to developers. I’ve heard people describe the version number that users get to see as “a branding issue” — and that’s not far off the mark. After all, Windows 2000 (to name an example) was really Windows NT version 5. For branding reasons, though, Microsoft decided to rename it.

So from a developer’s point of view, it makes sense to distinguish between version strings to be displayed to the user, and version numbers. It’s convenient to speak about version strings, and those allow the type of branding mentioned above — and it also suggests that there is no semantic meaning to them. If you want to check for compatibility at run-time, numbers are far more convenient.

After I slagged off Android in my previous post, it’s only fair that I should praise it now: Android’s developers have understood that there should be a difference between user-visible and semantically relevant version numbers, and have provided a mechanism with which both can be defined for a software package independently.

More precisely, the manifest file for what an Android package contains includes the following:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app"
    android:versionCode="16"
    android:versionName="1.0"
  >

Versioning for Package Management

Android itself has no use for the versionName attribute. It uses the versionCode attribute to determine whether a package installation is an upgrade — if a package with the same package attribute and a lower versionCode is already installed, an installation counts as an upgrade.

One of the things this example highlights is what version numbers can be used for. It should also be obvious that what they can be used for is strongly tied to the semantics one assigns to these numbers. In the Android case, the minimal package management the OS comes with is interested in upgrades versus fresh installations — and for that purpose, a single strictly incrementing package version number is the most useful.

That begs an obvious questions: what should version numbers look like in order to be useful for dependency management?

The bigger question behind that, of course, is what dependency management should do. At it’s simplest, it might be possible for developers of a software package to specify that their software uses another package in a specific version. Using Android’s terminology (because it’s already introduced), I might want to specify that my software uses “com.example.app” in version “16″.

That’s certainly a safe approach when it comes to dealing with compatibility issues. If I’ve developed my software using version “16″, then it’s safe to assume it’ll run best with version “16″. But what if that version included a bug? What if the vendor of “com.example.app” issues a bugfixed version “17″? Shouldn’t users of my own software benefit from that?