This blog has been moved to http://info.timkellogg.me/blog/

Sunday, July 10, 2011

Semantic versioning

I've seen some interesting software version sequences. Like Windows 3, 3.1, 3.11, 95, 95, ME, XP, Vista, 7. Or Oracle DBMS v5, v6, 7, 8, 8i, 9i, 10g , 11g (what does the g mean??). I've seen all sorts of version schemes to designate major versions, minor versions, patches, and other types of releases. (The worst ones are always when marketing gets involved).

Tom Preston-Werner formalized the major-minor-point release (X.X.X) scheme at semver.org. I highly recommend anyone who considers themselves a professional developer to read every word in the article at semver.org. The beauty of semantic versioning is that there isn't anything new or innovative about it at all. It's all what you already know to be true. All versions <1.0.0 are development versions. Once 1.0 hits, the public interface is solidified. If and only if you break backwards compatibility you have to increase the major version. Minor versions and point releases (1.X.0 and 1.0.X) are for various levels of new features and bug fixes.

When you release software labeled with semantic versions you make it easy for people to quickly asses how significant the release is (I might skip a point release and upgrade to minor releases, but I might avoid a major release due to the incompatibilities it might cause). It also forces the developers to exercise restraint in breaking compatibility with previous releases.

The trouble with semantic versions in the corporate world is that marketing always has ulterior motives. They want to release a major version to make the product feel alive; they want to downplay breaking changes to a minor version to keep customers; or they want to introduce new terms that mean nothing to the average user (XP for eXPerience, Vista because it sounds cool). Those names are great for development code-names but they detract from a buyer's experience (I use the term buyer loosely to mean any potential user) in determining compatibility between products.

In .NET assemblies, there are four segments supported with the AssemblyVersion and AssemblyFileVersion attributes (major, minor, build number, revision). This seems fine until you want to release alphas, betas and release candidates. The semantic version for a 1.0 beta release would be 1.0.0beta1 indicating that this is the first beta for the 1.0.0 release (you can use any string of alphabetical characters, not just beta). In a .NET assembly you do this as follows:

[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0.253")]
[assembly: AssemblyInformationalVersion("1.0.0beta1")]

The new attribute here is obviously AssemblyInformationalVersion, which is used to specify more arbitrary strings. It will show up in the Windows properties dialog as the assembly version (otherwise AssemblyVersion will be used). Also, the AssemblyFileVersion is used to indicate build numbers. So while working on the 1.0.0 release, we also have a continuous integration environment like Teamcity or Hudson building the code each night and incrementing the build version. However, continuous integration environments shouldn't need to have any impact on what you actually tag the version as.

As Tom says in the article, kinda sorta following the standard doesn't reap much benefit. But once we all start releasing software that conforms exactly to this standard, then users can more efficiently understand which two components are compatible and which aren't. I believe this applies to all software, not just software that supplies a public API.

2 comments: