Most developers use version numbers for their software. It’s considered a ‘best practice’, but version numbers are overused and give you a false sense of control and compatibility. Use the simplest versioning scheme possible, where versionless is the simplest.
Rationale
What is a version number? It’s a label (doesn’t have to be numeric) that identifies one particular snapshot of your software. Usually there is one overall version number for the whole system, even when components of that system have their own versions. Using this label, anyone can reason about the state of the code for that label. Users might say, in version IE 9.0.1.2 there is a bug when I try to print. The developers will know exactly which state the code was in for that version number and should be able to find and run that version (and fix the bug). Summary: you need to label revisions of your code to refer to it later.
Numbers are silly
So far, so good. Version labels are useful. But in stead of labeling the software with a date of release, the name of the latest feature, most developers use numeric labels. And not just a sequence number (1, 2, 3), but fancy numbers with dots! Giving your application a version number like 15.0.12.21.h makes it (and you) look really complicated and smart, don’t you think? Have you seen the Chrome version numbers? Anyway, let’s go into these version numbers more deeply. A typical application, let’s say a website for creating blogs, releases these versions:
- 1.0
- 1.1
- 1.2
- 2.0
What does that mean? Well, convention says:
- first ever release
- small change
- small change
- big change
That’s it, nothing more to it. But the numbers look more professional, don’t you think? Although list 1 and 2 have the exact same meaning. And was the change from 1.2 to 2.0 was really that big? We don’t know. What this developer deems big, might not be so big and worthy of a ‘major’ version bump for others. So why use numbers at all? Why not use descriptive names like:
- ‘first basic YourBlog release’
- ‘fixed bugs in login’
- ‘fixed bugs in page-saving’
- ‘redesigned UI’
- ’2011-1-10 first basic CMS release’,
- ’2011-2-1 fixed bugs in login’,
- ’2011-2-9 fixed bugs in page-saving’,
- ’2011-3-2 redesigned UI (big change)’.
My Application is an API
Maven: WTF?
Maven doesn’t help in making people steer clear of the number fetish. When you create a new maven project. The initial version for you module is: 0.0.1. Yes, not one dot, but two! You’re going to be doing some serious API-building business. No, you’re not.
What does that mean? By convention, 0.0.1 means ultra-pre-beta-alpha release. It’s probably just prints ‘hello world’ in a console. So you start building and maven increases your version with every release you make. 0.0.1, 0.0.2, 0.0.3. You’re not making much progress, so after a few weeks you make the bold move and change it to 0.1, your first pre-beta-alpha release! Or is it, perhaps it’s already live, in production and making money. When do you switch over to 1.0? When all the bugs have been fixed? The first time you go live? 1.0 means done, right? Stable, right? Yes, it does. But your website is never done, your GUI will always have issues so there is no 1.0!
I find when building whole systems, there is never a clean cut release. The first public release is not much different from the one before or after. So stop fiddling with the numbers.
Just to get back at the API argument, when you release an API to the world, there will be a 1.0. It’s that contract again, meaning: this API is stable and ready for production use, it has undergone testing and everything. This number means something because your communicating it explicitly, it’s in the product you ship (like commons-lang-1.0.jar). Your website just has a url, your GUI an icon, no version.
Version-less coding
Some code doesn’t need version numbers at all, it’s just code. If it’s checked into source control (on a particular branch) it’s usable. No 0.1 release or 0.1-SNAPSHOT. Just the code. If I want to make change that breaks stuff, I’ll create a separate branch. Maven doesn’t allow this, it’s basically duplicating what my source control system can do better (track revisions). For libraries, I might want this, but for my main project, I don’t. One of the reasons these version numbers are still so prevalent, is that Maven requires a version number. Starting with 0.0.1 will start you off thinking you need a complex version numbering scheme.
The build number alternative
I propose a complete alternative to using version numbers. It’s simple: build numbers and labels. Every time you build your system, for instance in your CI tool (like Hudson) it gets a build identifier, let’s say a timestamp. That number might be set in your source control as a label or the revision of the code might be stored alongside the build number, either way the build number will be a reference to a specific state of your code, but also a specific attempt to build that code. Sometimes you have to build the same code multiple times to get a good release (your build procedure might have issues). Now the build numbers are just a sequence. You can label releases that are actually going out for release, so you can refer to them later. Using the build number, you can even pick up the exact artifacts from that build.
- 2011-01-01-1543 – ‘added new content type’
- 2011-01-02-1218
- 2011-01-02-1543
- 2011-01-02-1743 - ‘improved render time’
- 2011-01-03-1109
Most CI tools (like Bamboo, probably others too) even support labeling a build.
One extra benefit of this, is that your code doesn’t have to contain version numbers. I think it’s a smell that the version of the code, is in the code. The version is something external to your code, your source control system has to deal with revisions, not the code itself. You’ll see that a lot of web projects don’t have a version at all, it’s just the code.
So, using labels in stead of dot-numbers, everyone will know what the version entails but you don’t have to worry about the numbers anymore. So, let’s make it easier!
As you say: “a lot of web projects don’t have a version at all, it’s just the code.” And that sucks. Web projects, like any piece of software, have bugs, and we do need something of a version number to refer to it if we want to solve them. When a serious bug emerges on your production web site, you don’t want to have to spend precious time hunting down exactly which SCM tag corresponds to the current release in that environment; you want to open the page and see at once which version you’re looking at. A good example would be the Bamboo software you mention in your blog: just check out the second screenshot at http://www.atlassian.com/software/bamboo/overview/tour/screenshot-tour – at the bottom of the page, it reads “3.4-SNAPSHOT build 2802 – 20 Oct 11″.
Allowing your web application to show the build tag requires you to rely on an external CI environment to add this information to your application at build time. I’m not saying that this is a bad thing, but it does mean that you can only test this functionality after committing it to source control, which feels like a bad practice. Why not make life easier for everyone by using the pom.properties file instead, that Maven includes in the WAR every time it builds, even locally? I didn’t think of this myself, Christian Kaltepoth did: http://chkal.blogspot.com/2010/07/display-maven-artifact-versions-in-jsf.html. But I do use his artifact in all my projects.