Version Numbers – A Developer’s Perspective

As a developer I have used version numbers but never gave many thought about it until recently. I know I have had some issues with it where not explicitly enough specifying dependency version could break things with new builds. On the other hand the usage of version numbers of internal libraries was always non-existing. In this blog post I will go deeper about how I experience version numbers from a developer’s point of view.

I worked a lot with Maven, which has a field to specify the version of the application. While this may sound helpful, I haven’t seen it being used by any of the projects I am on. The version always remained at 1.0.0-SNAPSHOT. Note that the projects I have been working on are all end-user applications, and no libraries meant to be used by an external party. I can imagine that in the latter case the usage of the maven version is vital.

The version numbers of internal libraries was always set to be 1.0.0-SNAPSHOT, because we never updated it in the maven file. External dependencies had fixed versions. I have seen the same being done with Angular. Although Angular (similar to Python) has a neat way of specifying versions which allow a range of versions, we stopped using it and went for fixed versions. Why? Because we had libraries of which a patch upgrade broke our entire application. This show that just using a version number doesn’t fix your problem, you have to attach guarantees to it for the people who use it.

But just because we didn’t update the version in the Maven file, doesn’t mean we didn’t have a versioning system. We had one, but it mainly existed on our git branches and the portal where they would be made available. However, all the same guarantees where made with respect to compatibility.

Since I now switched to C++, and rely on CMake things are different. While CMake does have a way to set the version of your project, there is not automatically discovery of dependencies, so I guess it is more for internal documentation. Dependencies for a C++ project can be split up in two categories, you have the shared libraries that should be running on the system and those you statically compile with your application. The first is difficult to have control over, well actually the version number is normally included in the library name, so that fixes the problem. For the latter CMake has a command to download projects with a specific version from a Git, Subversion or Mercurial repository as well as a plain URL.

Version numbers are a bit of a hot topic at my current work place, and this is mainly because until recently (and it is still partly in place) every single merge to master required you to bump up the version. You can imagine this is a bit of an annoying job and causes a lot of merge conflicts. As a result there is now a movement towards the other direction, where we would no longer maintain any version numbers but rely on a git branch/tag to keep track of it.

This is identical to the system I have been working with before, but the major difference is that our current application is much more split up over many small components, each with their own repository. While I am not convinced by this current architectural design, it is some legacy code that needs to be considered. So when enforcing the ‘all masters must be compatible at any time’ you do remove the initial idea behind splitting up the components: they should be able to be developed/updated/executed independently.

There is nothing wrong with a requirement that your code should only be compatible with the current latest versions, as long as all of your code is packaged, released and installed together on a single system. If your application is separated across multiple systems you will have to update all of the systems at the same time, meaning you have more downtime. It also blocks small incremental updates since you can not update a single component together with a new version of the library as it might break other components.

Once you have the mindset of only keeping the current ‘master’ working with each other it will be hard to get rid of this mindset, so it may be better to immediately start caring about using version numbers. This will allow for a much easier way to grow towards the future.

Enforcing that all ‘master’ versions can work together also means that if you update a library, all applications or components that use that library will have to be updated at once as well. With a version number you can upgrade components on the go as they need it. It might even be a bigger problem if you don’t have control over all components, but they are being developed by multiple teams. A change done by one team can break the code of another and force them to update. Teams that become this dependent will cause friction and it is a bad way to work.

As always it depends a bit on the type of application you are developing and the setting in which it is being done. There is no problem to go without a version number if it is a single standalone application that you build yourself. But for bigger enterprise applications, using version numbers is a good idea, even if you don’t technically need them (yet), enforcing them later will be harder because of the mindset that needs to be created.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.