The ABC's Of Dot Releases
Over the years, I've seen various naming conventions for software versions, also known as release numbers. “v2”, “7.0.4321”, “11.3.5432a SR-3”, “RTK0320-R5-32”, “Chicago”. What do these cryptic numbering schemes mean? Which convention should your organization adopt? And more importantly, why should you even care?
Who Cares?
When things are running smoothly, nobody cares. Having a “good” versioning scheme certainly doesn't add any functionality to the product, improve its quality, or optimize software quality attributes. But when problems arise in the field, then everyone cares.
Imagine the two following scenarios:
- A customer currently has 3.0 installed. He notices that 3.1 is now available, so he goes ahead and upgrades his system. Once the upgrade is complete, he launches this “latest and greatest” release only to realize that it's not backwards compatible. In other words, he can't manipulate the files that he had originally created with 3.0. Worse, there's no way to “downgrade” the release. Shouldn't 3.1 be backwards compatible with 3.0?
- Your latest stable branch is “Chicago”, and your development branch is “Boston”. A bug is detected in “Detroit”. The developer commits her fix to the “Detroit” branch, but doesn't port it to the more recent branches. Why? Because there's no (easy) way to tell which branch was created after “Detroit”.
The Not-Quite-Standard Convention
There is no such thing as a “standard” versioning convention, but there is one scheme that's more common than others. I call it the “A.B.C.” convention, where A represents a major release, B a minor release, and C a “patch” release.
Abbr. |
Description |
Examples |
| A | Major Release | Releasing on a new platform (e.g. .Net
vs. J2EE)
Adding significant functionality Modifying the API Significantly altering the user interface (e.g. new sections, redesign of existing screens) |
| B | Minor Release | Adding 3 incremental features Implementing bug fixes Slightly altering the user interface (e.g. new button) |
| C | Patch | Minor bug fixes (defects, security patch,
slight performance improvements) Fixing syntax errors on the user interface |
The ABC's of Quality
While the main goal of a major release is to add significant functionality, a minor or patch release should improve the quality of the load. Generally speaking, a 3.2.3 release is more stable than its 3.0.0 predecessor or even a 4.0.0 one because 3.2.3 contains 2 minor releases and 3 patches (in other words, a whole lot of bug fixes and very few new features).
That being said, some organizations use this concept as a marketing tool. I've seen companies skip from 1.0.0 to 3.2.3 after their customers refused to install a dot 0 release because “they're concerned with its stability”.
From a marketing perspective, this strategy makes a lot of sense. If a version number implies quality (or lack of), then why not adjust our product versions accordingly? My only concern is that you can only “trick” your customers so often, and if everyone adopts this practice, then version numbers will become meaningless.
A Word on Backwards Compatibility
Generally speaking, releases should always be backwards compatible. However, those of you who are truly pushing the envelope know that maintaining backwards compatibility is sometimes impossible – or at the very least difficult.
As a golden rule, minor releases and patches should be extremely safe to deploy and should be 100% backwards compatible. If, after careful examination, you decide that it's ok to introduce a feature that would break backwards compatibility, make sure you do it in a major release. Furthermore, clearly indicate the compatibility issues in your Release Notes, and document a manual upgrade procedure (if one exists) with a well-written MOP (Method Of Procedure).
Internal Releases
While the A.B.C versioning scheme clearly designates to your customers how various releases relate to each other, it might not be practical for your development team. Since even C releases are only released every 30 to 90 days, your developers need a finer level of granularity to communicate when/where bugs were introduced and/or fixed.
My recommendation is to append a number to the overall tag that increments every day. For example, if 5.2.0 was released 12 days ago, today's load should be tagged 5.2.0d12 (where “d” simply signifies that this load is an internal development load).
When To Branch
Branches (also referred to as “streams”) allow the development to be partitioned. They prove to be useful when there is a need to perform modifications in one branch without affecting the other.
Because major and minor releases can always be patched, A or B loads require the creation of a new branch. C releases, or patches, don't.
Let's say you ship 1.2.0 to one of your customers. At the same time, you promise another customer some incremental functionality in your next minor release (1.3.0) that will take you 6 months to implement. There's a strong possibility that the 1.2.0 customer will encounter critical defects that they will want addressed ASAP. They can't wait 6 months, and you can't halt 1.3.0 development. You therefore need a load between 1.2.0 and 1.3.0. You need 1.2.1.
Since 1.2.1 and 1.3.0 development will occur simultaneously, you need two different streams.
Patches should never be developed in parallel. In other words, you wouldn't work on a 1.2.1 patch and a 1.2.2 patch at the same time. Companies who attempt to do so always end up with a management nightmare. Trust me. Working on multiple patches on top of multiple minor and major releases is a development practice that you want to avoid.
Fix as many bugs as possible in the 1.2.1 release, tag the load, and then start working on 1.2.2. Once again, don't branch C releases.
When To Release
Releasing stable loads requires overhead. Major, minor, and patch releases all need to be thoroughly tested before being shipped to a customer. As a result, you don't want to release loads too frequently. Then again, not releasing software frequently enough means that you run the risk of releasing your latest and greatest features after your competition, which can be devastating to your business. So when should you release software?
If you're developing a totally new product, you'll want to release on a relatively frequent basis as illustrated in the following table:
| Abbr. | Interval |
| A | Every 12 months |
| B | Every 2-3 months |
| C | On a per request basis only* |
* Because of the short interval between B releases and the (usually) low number of customers who deploy 1.x and 2.x releases, C releases are rarely required at this stage of the product lifecycle.
Once you reach the 3.0.0 milestone and your product becomes more stable, you should slow down your release schedule as per the following table:
| Abbr. | Interval |
| A | Every 24 months |
| B | Every 6-9 months |
| C | Every 30-90 days |
Conclusion
Tagging and branching software should be very straightforward. However, I've seen many companies needlessly complicate their process by implementing ridiculously complex versioning schemes. And I've seen even more infuriating their customers by shipping them a minor release that breaks backwards compatibility, or a patch release that ends up having more bugs that its predecessor.
If you're managing a complex software project, I'm sure you have enough things to worry about. Tagging and branching releases should not be one of them. Adopt the A.B.C convention and, more importantly, follow my advice regarding quality, backwards compatibility, and release schedules. It will make your life that much easier.
This article was originally published on www.gantthead.com.

