Version Naming

This article was originally published in php|architect in February 2009 and I published it mostly as it appeared in the magazine shy of the odd formatting to fit the blog format better.

Standards evolve all the time but this specific standard has not changed much at all since I wrote my article but as always for something written a year or two ago, take it with a pinch of salt :-)

PEAR has been around for many, many years, and thus has accumulated a lot of knowledge on how to run a large-scale project.

PEAR has run into countless hurdles along the way that had to be solved in one way or another. As a result of getting over these hurdles, we have produced good things that affect the whole PHP community and also things that well…let’s face it, didn’t help PEAR or PHP a whole lot.

But, how do we bring that experience from the knowledge bank of PEAR and give it back to the community, so other projects can learn from us and steer clear of what we did wrong and embrace what PEAR did right.

One of the things that really makes PEAR what it is today are the standards we have evolved for the past couple of years. A lot of other projects and even companies have embraced large chunks of those standards as their de facto standard for PHP userland code.

Just to name a few standards:

  • Distribution system (channels, packages, package.xml)
  • Coding Standards
  • Version naming
  • Directory layout
  • Backwards Compatibility and what that entails
  • And many others

If you want to read about the distribution system, you can grab the 2009 November and December issues of php|architect where I wrote about it in good detail, or you can wait for me to publish those on my blog.

Version Naming

Let’s start by talking about the version naming standard and why it’s important.

Now don’t get me wrong, it’s not like PEAR invented the need for version naming, be it for PHP projects or the software world at large, but the fact is that PEAR was one of the first, if not the first, large-scale PHP project that had more than one concurrent release at a time. This fact required a proper standard in the end.

So, almost 5 years ago today, the PEAR group at the time went ahead and formalized a standard to keep the version naming more consistent, yet still working with the version_compare function.

The document they produced can be accessed from http://pear.php.net/group/docs/20040226-vn.php, but I will attempt to simplify it a bit.

First, it’s important to understand that there is a difference between version numbers and version state and how they interact. Let’s look at how the basics of the version numbering system work. Consider x.y.z for a second, now let’s translate that into something human readable.

  • x = Major release number
  • y = Minor, used for feature additions
  • z = patch level number, used when it’s purely

only a bug fix release

Now let’s have a quick look at the states, dev, alpha, beta, RC or stable (listed in the order of code maturity). So what you end up with is x.y.zstate (Note the lack of space there) except when you have a stable release. In PEAR, you might see version namings like so: 0.5.6alpha1, 0.12.0beta3, 1.0.0RC4, 1.2.0 and so on. With this system in mind, we need to see what each state and number incrementation really means for you and your project.

Quite often, I see people do their first release, and for some unknown reason, they decide that 0.0.1 is the best version, swear by it even. In the version naming standard we have in PEAR, that is not allowed because when you are releasing the first release you are not fixing bugs, you are adding new features, so the first release should always be 0.1.0, at the very least.

Something that happens fairly often as well is that people do their first release as 1.0.0 with a stable state, even though their project doesn’t truly have a stable API, such as, or even a stable product in general. Perhaps it’s because they believe they managed to get it very stable, but the fact is, no matter how stable you think your product is for the first release, always release the first one lower than 1.0.0 stable.

Keep in mind, when you go stable, stay stable! Don’t start messing up the API in a way that people will have to alter their applications, this tends to be called BC, or backwards compatibility.

Backwards Compatibility

Now what is backwards compatibility? In short, it is when I, as an application developer, pick library X to use in my application and pick release 1.2.0 to start utilizing the API of library X. Even though I don’t follow the development of library X, if they follow a proper, no-BC-breaking approach, then I should be able to upgrade the lib from 1.2.0 to 1.6.0 without having to change a single line

in my code. If a BC break would have occurred between 1.2.0 and 1.6.0, then there is a good chance that my application would stop working with such an upgrade. So BC breaks should only happen below stable, preferably only in the alpha state, if possible.

Food for Thought

So, I perhaps didn’t cover all that much of the version naming standard, but I do believe I got my point across and those interested in learning more can go to the link I supplied above to get a better idea of how this all works together beautifully.

A prime example of why it’s good to have a set standard on the version naming would be when Matthew Weier O’Phinney of Zend Framework fame contacted me in late 2008 to determine whether PEAR had this kind of standard. The Zend Framework team was having internal discussions in regards to version naming, especially for their preview releases, better known by other folks as alpha releases, where new api changes are introduced but still not considered stable or that an API could possibly break before the final release.

In the end, Matthew managed to convince them to use alpha/beta states on the package level while allowing them to use PR (Preview Release) for the website and announcements. This allows people to use version_compare on Zend Framework for future releases, potentially use a PEAR channel for distribution and to have proper stability states for what the release is supposed to reflect.

I felt like this was a very good example showing how using a well-established naming convention benefits the whole community and makes things a lot clearer for those familiar with said standards.

Hopefully this is as useful to you as it was to me and the projects of which I have been a part. It has, at least, been highly successful to PEAR and numerous other projects.

4 Comments to “Version Naming”

  1. First nice post, Its not often that people actually dive into stuff like this and I think it should be done more often. With that said…

    I have become very weary of the “number” scheme that is currently in the world of web development. It doesn’t really fit anything that we do, but it has been forced in because that is the way it has always been. There are currently projects with thousands of contributers that are trying to maintain this numbering scheme and you can just tell from the outside working in that it doesn’t work. More so now in the age of forking – this strategy just doesn’t work. So now the problem becomes where do we go from here to grow past the concept of version numbers into version X.

    As an example to this Chrome as found great success targeting “Features” instead of a number. Being at 2.0.0 means very little in relation to HAVING x y and z. Granted this doesn’t give the kind of company wide internal tracking most would want (“It was the release with Y”), but I think it is a step in the right direction.

  2. I must admit, since I wrote this post back in 2009 I have changed my mind a bit as to how I want to see version schemas work on software, in fact I lean towards the Chrome model which is as you pointed out is more in line with the forking approach people are taking these days.

    Stepping back a bit tho I think it’s very important to look at the application versioning differently than you would a library. Generally applications are not exposing many end points for people to plug into and thus can have a more fluid version schema and laxed rules on how ABI / API compatibility is handled, where as a library is exclusively used through the APIs and as such becomes more important to know when when an backwards compatibility is broken.

    So my current take is that application versioning should be rather fluid (rapid increments) while libraries should stick to the version schema I outlined above; Applications are a big chunk of work with multiple people working together on it and pulling together many different libraries while a library is more contained and should be fairly small (if it isn’t then it probably should be split up into smaller libraries). As an application developer I at least like to use libraries that don’t blaze through numbers like candy as they are the foundation of anything I build.

    I would be interested in hearing what kind of model you believe fits for libraries – I for one have a hard time seeing the application model fitting for libraries but I’m all for hearing new perspectives :-)

  3. One of the things that has always been a confusion for me as it’s inconsistent across projects is what the suffix is pointing to… For example:

    0.5.0RC1 will become 0.5.0 in some projects but 0.6.0 in others

    I think this is also enforced by the Pear standard as it is not possible to go from 0.5xxx to 0.5 as this is seen as a “backward” step, even though in human readable terms it is forward.

    I should be able to go from 1.0.0RC1 to 1.0.0

    Thoughts?

  4. A standard is obviously suppose to address inconsistencies but it depends who subscribes to the ideal, tho what I lined out is fairly common practice as such; Wish more people at least read similar documents :-)

    0.5.0RC1 -> 0.6.0 jump is a different release model and thus requires a tad altered version schema, what those people are doing is using odd numbers as development / beta releases where as even numbers are stable; This is something the Linux kernel used to follow for a good while until they moved to the model I described above.

    As far as 1.0.0RC1 to 1.0.0, that’s exactly how PEAR works; 0.5alpha1 goes to 0.5 (even tho I advocate 0.5.0 as it keeps consistency but 0.5 implied the final 0 and works fine with version_compare())

    Does that answer your questions?

Leave a comment