4 ms·
A core problem is that the current system conflates two subtly different notions of version: the low-level package manager version (is it backwards compatible?
by tikhonj 12y ago
A core problem is that the current system conflates two subtly different notions of version: the low-level package manager version (is it backwards compatible? will it build?) and the high-level person version (is this the same library with some changes, or is it a new generation or significant redesign?).
The first notion is needed for keeping our code stable but keeping up with bufixes and security patches. The second one is needed to deal with design issues: will this change require a lot of reworking? Will it change the underlying model or abstraction in the library?
Both of these are important. But because Semver requires bumping for any breaking changes—even if they are semantically minor—it can only address the first, low-level notion of versioning, not the second.
A possible solution? We can have two minor version numbers:
4.1.0.2
Patches and backwards compatible changes work as always. But if you are making a breaking change, you have two options. If it's not too big, just increment the first one:
4.2.0.0
But if you're really changing things up and creating a new generation of your library, go for
5.0.0.0
Of course, the difference between the two major numbers is not well-specified. But that's fine! From the more technical, low-level perspective, it's no different from normal Semver: any change in the major version (either of the two numbers) can be breaking. It just also lets library authors send an additional signal to developers about the scope of the change.
For example, this scheme gives more information on how "stable" a library is. If the second major number is high, it means there are a lot of minor breaking changes; it would take a bit of active maintenance to keep up, but as long as the first major number is not changing, these steps won't be radical.
Personally, this approach makes a lot of sense to me. It's also more or less what Haskell packages use according to the "package versioning policy", and it seems to work pretty well. (There are some other pervasive issues with Haskell version numbers, but not related to how they treat major versions.)