Tip: Versioning

I was catching up with a colleague today at a coffee shop about his OSGi-based product and the topic of versioning came up (he also bribed me with free espresso shots). My colleague’s company recently released the “2.0” version of their product and were ready to move to the next release (3.0). The common pattern they were using was to simply artificially synchronize all plug-in (bundle) versions for each release, regardless of the actual changes in any particular plug-in.

In my opinion, this is an OSGi anti-pattern and is bad because it effectively makes your plug-in versions meaningless. What do I mean by this? Well, first, imagine a case where nothing has changed in some common utility bundle between the 2.0 and 3.0 releases. For the sake of argument, let’s say this common utility bundle also exposed some API. By artificially bumping the version, we can have some unintended downstream consequences. What happens if clients were depending on that common utility bundle and scoped their version ranges to [2.0.0,3.0.0)? Clients would break if they moved up to the new release even though they didn’t need to. On the other end, how do your clients know how to scope their version dependencies if they don’t know what your version numbering scheme means? That’s just one of many other reasons I think can cause problems when you don’t assign meaning to versions.

Is there a better way? I think so, let’s take a look at how versions work within the Eclipse SDK. In Eclipse/OSGi, version numbers are composed of four segments: three integers and a string respectively named:

‘major.minor.service.qualifier

Each segment captures a different meaning:

  • the major segment indicates breakage in the API
  • the minor segment indicates “externally visible” changes like adding new API
  • the service segment indicates bug fixes and the change of development stream
  • the qualifier segment indicates a particular build

How does this work in practice? Let’s learn by example by looking at few plug-ins in the Eclipse 3.4 release:

  • org.eclipse.equinox.p2.core (1.0.0)
    • Since the version of p2 is 1.0.0, we can assume that it’s a brand new plug-in in the 3.4 release
  • org.eclipse.pde.core (3.4.0)
    • Since the version of pde core is 3.4.0 and the previous version was 3.3.100, we can tell that new API was added in the Ganymede release
  • org.eclipse.ui.forms (3.3.100)
    • Since the version of UI Forms is 3.3.100 and the previous version was 3.3.0 we can tell that there were some bug fixes only included in the Ganymede release… no API added

See what you can infer now that versions actually carry some meaning? It’s my hope that this tip at least makes you think twice about how you define your API and version your plug-ins. It’s not an easy task but I think it’s important aspect of any modular system to make your versions mean something… otherwise, what’s the point?

So the advice I left for my colleague was he can call his product version whatever or give it a cool code-name, but be cognizant about the way plug-ins are versioned. Thankfully, he agreed and I got another shot of espresso 🙂

On a side note, in the Eclipse 3.4 release, PDE added API Tools to make it even easier to keep track of your API and version information between releases. For example, let’s see what happens when I use API Tools with PDE. Let’s say I was naughty and added a new public method in an API class without modifying the plug-in version, what happens?

Ah, it knows I was naughty and informs me I should bump the version and even informs me to add a missing @since tag… how nice! Feel free to give API Tools a spin if you want to help manage the version story within your OSGi-based application.

Thanks for reading and feel free to comment about your versioning horror stories 🙂