Semantic Versioning and why you should implement it correctly in your applications
Chances are, at some point in your programming career, you downloaded some library to use in your code. When you download an external library, it will include a version number, making upgrading and obtaining documentation for your specific version of the library simple. While the version number appears to be an arbitrary mix of numbers and decimals, it can reveal a wealth of information. This is exactly what semantic versioning is about.
Definition
Semantic versioning is a set of criteria that many libraries follow to determine how to increment their version numbers. A semantic version will always be three numbers separated by decimals, indicating the library's major, minor, and patch versions. Semantic versioning follows the format shown below.
MAJOR_VERSION.MINOR_VERSION.PATCH_VERSION.
This means that the semantic version 1.14.2 refers to a library with major version 1, minor version 14, and patch version 2.
I mean that's great, but what do the various variants mean? Here's a verbatim statement from the official semantic versioning documentation.
Given a version number
MAJOR.MINOR.PATCH
, increment the:
MAJOR
version when you make incompatible API changes,MINOR
version when you add functionality in a backwards compatible manner, andPATCH
version when you make backwards compatible bug fixes.
Let's go over the reasons for upgrading each version in more detail.
Patch Version
The docs states that a patch version should only be changed when backwards compatible bug fixes are introduced. Patch versions are frequently updated when bugs are identified between minor releases that must be resolved immediately. One essential note about incrementing patch versions is that the library's public API cannot change in any way. The only thing that can change is the restoration of broken functionality.
Minor Version
The minor version is slightly more involved because it will be updated if additional backward-compatible functionality is added to the library. For example, if a math library added the ability to calculate sine and cosine, the minor version of that library would need to be updated when those new features became available. It is also critical to reset the patch version when a new minor version is issued. For example, if a library is version 2.3.6
and a new minor version is released, the new version number will be 2.4.0
. Another reason to increase the minor version number is when a library method is deprecated. When a function is about to be removed in a major version, it is usually standard practice to deprecate it in a minor version before the release so that users are aware that this technique will be removed in the next major version update.
Major Version
The last version number, the major version, is only incremented when the library's public API undergoes breaking changes. This could range from substantial breaking changes, such as rebuilding the entire library, to minor breaking changes, such as redesigning a single library component. The crucial thing is that whenever a breaking change is introduced, the major version of the application must be updated. When the major version is updated, the minor and patch versions must be reset as well. For example, if a library is upgrading from 1.12.6
to 2.0, the new version will be 2.0.0.
How To Start Using Semantic Versioning
Semantic versioning is good for making it apparent what changes are happening in a library, but what if your library is just getting started? Having to upgrade the major version every time the public API breaks is a lot of work because things will change quickly once a public API is decided. As a result, semantic versioning requires a unique condition for dealing with new, fast changing libraries. If a library is in the early phases of development, a major version number of 0 can be applied. For example, the initial version of a fresh new library would be 0.1.0
.
During this initial development version, the minor version can be used to signal any new feature or breaking API change, as most work in early development will result in API modifications. Once the public API is established, a release to version 1.0.0
is recommended so that breaking changes may be easily tracked. This also informs potential users that the library is stable and unlikely to include breaking updates.
How To Handle Pre Release Versions?
Many larger libraries with a significant user base prefer to issue beta versions of their libraries for early adopters to test and find bugs in. Semantic versioning supports the concept of pre-releases. If a library was in version 2.3.4
and the maintainers wanted to create a beta version of their 3.0.0
release for early adopters to test, they may do so by naming the version 3.0.0-beta.1
.
The key to establishing pre-release versions like this is that they must follow the patch version and begin with a hyphen. The pre-release version may contain any combination of letters, numbers, or hyphens, with each part separated by a decimal. For example 3.0.0-0.1.0
is another valid pre release version.
Conclusion
In Summary, semantic versioning simplifies the process of upgrading and obtaining documentation as a library user. It also makes it easy for the library maintainer to follow rigorous guidelines when developing new versions of their library. It would be practically hard to handle library dependencies without semantic versioning, therefore utilize it the next time you develop a package or an app.
Subscribe to my newsletter
Read articles from 9th Tech directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by