Hacker News new | past | comments | ask | show | jobs | submit login

What are SemVers current flaws? Maybe I missed a link in the article.



Here's the largest, IMHO: none of the matchers are in the spec. It purely talks about versions themselves, not how you specify ranges. It's only really got half of the important stuff in it!


Could you elaborate on this?


“Matchers” or “ranges” (even the terminology is split up thanks to the lack of a spec!) are not defined in semver. It only defines how to version a particular software artifact, it cannot answer the question “does version 1.2.3 fit the constraint > 1.0.0?”

Does that make sense? The “> 1.0.0” part is undefined. That includes things like “is that space required there?”, and so is an interoperabilty issue.


I don't see what's ambiguous in that.

> does version 1.2.3 fit the constraint > 1.0.0?

I would answer, yes, 1.2.3 is greater than 1.0.0. I can't see how anyone would interpret it differently.


How about "does version 1.2.3-alpha.3 fit the constraint "~1.2.3"? If you're asking "what the heck does a tilde mean?" then, yep, that's one of the current problems - it has a de facto meaning because the npm semver package started using it, and now it is adopted by some (but not all) semver implementations in the wild.


I should have used "x.y.z" instead of a hard number, as it kind of obscures the point.

The concept of "this is a thing I use to specify a range of versions", as a concept, does not exist in the spec. This means "> 1.0.0", in the context of the SemVer spec, is meaningless. This means you cannot answer the question, even though, as a human, you can intuit what's meant. Computers cannot.

(Additionally, there are other questions as I mentioned above. Is ">1.0.0" allowed too, or not? Getting parsers correct is important.)


That's an easy one. Try:

Does "<=2.3.4" include "2.3.3-some.prerelease"?

Justify your answer. :)


At least with Gitflow and Githubflow workflows, it is my understanding that we change the version number in the release/feature branch.

With that understanding in mind (regardless of it matching your understanding, I mean), then clearly, "2.3.3-some.prerelease" is in fact less than "2.3.4", or it would have been named "2.3.4-some.prerelease".

Therefore, I believe it is clear that workflow must necessarily be considered to understand SemVer.


So if a user has the version constraint ">=2.3.3 <2.3.4", should they get that pre-release version?


This is covered explicitly in the SemVer specification section 11[0].

The answer depends on if there exists a released "2.3.3" version, in which case, the pre-release is not selected, because pre-release versions have less priority than release versions.

The spec provides the following example:

1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.

[0] https://semver.org/#spec-item-11


But someone might well interpret it differently. The whole point is to define this stuff. There's no harm in writing down assumptions, even if they're ones everyone is making.


He didn’t say it was necessarily ambiguous, only that the syntax is not part of the spec, and thus someone could define “> 1.0.0” as meaning “redirect to the version 1.0.0” and it would still be SemVer currently. Although I don’t know exactly what that would mean, this choice is foolish given the current implementations of SemVer, perhaps it makes sense from a bash-user perspective.


Yes, but how did you come to that conclusion? Lexical matching, piecewise numeric matching? What's the programmatic way of determining that?

For a better example, how about version 1.9 vs 1.10? Or 1.9rc1 vs 1.9?


Your example does not follow SemVer.

If it did, however, your query would have a straightforward answer described in Section 11 of the Specification[0]

Here is their example for how to handle pre-release versions:

    1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.
The example shows that "1.9-rc.1" is less than "1.9" and both are less than "1.10".

So while it is true that many parts of SemVer are as yet unspecified, it seems to me (from these comments), that many people do not understand the already specified parts of SemVer, currently.

[0] https://semver.org/#spec-item-11


and yet my matcher disagrees, and there is no way to determine which behavior is correct.

the "no way to determine" is the point here, not the details of the example that was chosen.


I would love an unified matchers syntax. After dealing with ivy matchers, I very much prefer the npm/bundler/cargo style matchers, but would love them to all be exactly the same.


Me too! It's my personal highest priority, so here's hoping!


can you explain that for us?


I think the key flaw is that some people just don't like incrementing the major version number! It's a simple as that.


I propose RomanticSemVer:

{marketing}v{major}.{minor}.{patch}


I second that. The problem is that SemVer is conveying an extremely limited semantic meaning. "This is incompatible with that", yes, good to know. And then?

The derogatorily named marketing number instead used to indicate major changes and important increases in functionality. Now version number are meaningless: there is no way to tell if version 16.0.0 is supposed to be any better, or provide any more functionality, or incorporate any new concept from version 1.0.0. All it says it's that it is incompatible.

Somehow I get that this is the era of "evergreen" software, continuously and incrementally developed, and marketing numbers might be a thing of the past. But sometimes you need to express the concept that something changed radically and that a lot of new things have been introduced at once.


https://github.com/jashkenas/backbone/issues/2888#issuecomme...

> So, as I like to joke — not "semantic" versioning, _romantic versioning_.

> Given a version number MAJOR.MINOR.PATCH, increment the:

> MAJOR version when you make a major new release, or significantly update and/or stabilize the API.

> MINOR version when you add minor new features.

> PATCH version when you make tiny changes, likely to go unnoticed by most.

> This allows folks, immediately upon hearing about a new release, to get a rough sense of its scope.


As I see it, one of the main goals of semver is to allow automated tooling to predict what dependencies can be updated without breaking changes. And specifially in environments where the size of dependency trees was starting to make it really painful to do this manually (to get bugfixes and security patches, which matters!)

It's no coincidence, as the OP notes, that it was invented at about the same time as bundler was being developed -- one of the first of a new generation of dependency management tools that solved other problems in managing very large dependency trees, such that "how do I update to get fixes without breakage, it's too painful to manually figure out what versions for every dependency do that" _becomes_ a salient problem, _and_ can be a tool that can address that problem in an automated fashion, if dependencies use semver.

"romantic versioning" is more or less what everyone was doing anyway/previously. Semver was intended specifically to solve a problem this kind of 'romantic versioning' created, especially with very large dependency trees.

I often find this comes up in discussions of semver. If I'm right about the semver motivations here -- perhaps, if anyone on the new semver team is listening, the semver doc should be more explicit about this motivation. Because I find it often gets misunderstood in discussions of semver. And if you don't understand this goal, you're not on the same page in evaluating semver.


The problem is that in practice patch versions can break compatibility anyway.

On multiple occasions, I have run `npm/yarn update` with only patch upgrades, and had critical bugs.

And even if authors did follow SemVer in practice, fundamentally there is virtually no "safe" change -- bug fix, performance improvement -- that is impossible to produce issues in my code (because I might be holding it wrong).

SemVer would be nice if it worked. Romantic versioning is nice because it makes no false promises.


http://www.hyrumslaw.com/

    With a sufficient number of users of an API,
    it does not matter what you promise in the contract:
    all observable behaviors of your system
    will be depended on by somebody.
It's a nearly insurmountable task to make a change without breaking any users. Semver is an improvement over the status quo, and it at least means that when code breaks someone made a mistake.

I think the next potential step up from semver is a way for a library to run all public tests of its dependencies to look for new breakages. This is not a trivial undertaking, because tests can be slow, resource intensive, and flaky, but it's possible and incredibly freeing for a library or infrastructure developer.

I seem to recall some work in the rust ecosystem like this, but my search-foo is failing me right now.


We do that, yes. "Crater" is the name of the tool (also called "cargobomb" at one point).


In the ruby ecosystem, I think it's indisputable that both bundler and widespread use of semver resulted in huge reductions in pain of dependency management, including improvements in automatic updating to get bugfixes and security patches without breakages.

It's not perfect (not all dependencies even try to use semver, some have bugs in their semver versions), and it doesn't eliminate need for having and running automated tests after dependency updates, or eliminate all surprises or manual interventions -- but I think it's hard to argue that it hasn't been an improvement.

Now, typical "modern" (webpacker etc) Javascript projects can have, it seems, even an order of magnitude larger dependency tree than is common even in post-bundler ruby.

One would think this would make the problem being discussed here _even more painful_. I dabble in JS but am not really expert at it, but I think that's probably so.

So, if semver is not working to lessen the pain -- which is possible, although it's also possible it would be even worse without it -- why not?

I honestly think some of the answer is a lack of understanding of the solution being suggested by semver, which is why I think the semver docs should be more explicit. As I understand it, pre-yarn, JS toolchain didn't even have the equivalent of the `Gemile.lock` for managing dependencies, which to me is pretty crucial. I think there is probably a lack of understanding among some dependency maintainers on what they should be trying to do regarding backwards incompat, the definition of such, it's relation to version numbers, etc. And among dependency consumers on how this system is _meant_ to work, that it could even be _possible_ to automatically update in non-breaking ways, if your toolchain behaves well, if dependency authors behave well, and if you specify your dependency requirements accordingly.

But maybe with all of that, there is just something about JS and the way it is used -- or something about order-of-magnitude bigger dependency trees? -- that makes it much harder.

I'm not sure. You seem to be suggesting that the JS community ought to give up on any automated toolchain assistance in determining updates possible without breakage, and just resign to only updating dependencies after manual human review of changes in each one.

To me, that seems just plain infeasible when you have ~1000+ element dependency trees including many-levels of indirect depenencies you don't particularly want to know about. You're going to end up spending a huge amount of time trying to identify and apply relevant bugfixes and security patches in deeply-indirect dependencies -- or just have buggy and vulnerable software, with huge technical debt if you ever want to update to more recent versions of dependencies after a project has had it's dependency tree stagnant for so long.

On the other hand, the JS developer community seems to be willing to put up with levels of developer inconvenience that seem insane to me, and practically, many people in JS-land seem so far to have been managing their 1000+ element dependency trees entirely manually, somehow. So, I dunno. If this isn't generally seen as a problem in the JS community, then of course there would be no interest in a solution involving semver. I have trouble believing it won't be increasingly seen as a problem, in which case familiarity with solutions that have worked in other ecosystems would be important in working out solutions for JS... but who knows. (There is an npm representative on identified semver maintenance team, so I'd guess at least _some_ JS devs recognize the problem and are interested in a solution involving semver...)


I agree wholeheartedly, and yeah that would make a good FAQ entry. Thanks!


Haha, that's exactly who I was thinking of. I linked to it in a sibling comment.

I agree with him that having a digit that represents the "era" of the software that can spin on its own is useful.

My only problem is that MAJOR is still useful for API changes/breakage, even tiny ones. By adding the ROMANTIC digit, then you, the developer, don't have to be sentimental about MAJOR changes, and your users still know to read the changelog if it changes at all.

Because it's definitely true that sometimes MAJOR changes for massive reasons (e.g. 100% rewrite) and sometimes for trivial reasons, and semver doesn't distinguish them. It's hard to answer questions like "so when was the last big change to this library since my version?" just looking at semver major digits.

Of course, this is just bike-shedding given how entrenched semver has become, and I certainly prefer semver to what we had before: nothing.


I have projects where I intentionally maintain separate semver and user-facing "romver" (I like that name, I may use it moving forward) version numbers. Semver is at something like 18.x.y and Romver in development is currently at 2.z.w, and may jump "soon" to 6.z.w to match/replace an old VB6 app. For a while with 1.z.w, for simplicity to myself z was the semver MAJOR, but at this point they are almost entirely divorced.

ETA: The heavily broadcast user-facing version number of the VB6 app in its usage and marketing being a key reason for needing a "romver" at this point, because users clearly have been trained for decades to expect it.


I do the same thing, I'd assume a lot of people do. My API is at version 87.2.19, while my user-facing app (that nothing programmatically accesses) is 1.3.4.

If you maintain software that only humans interact with and does not need to be programmatically read, there is no reason to use semver.


On the flipside, I've long argued that maybe its time we deprecate/remove user-facing version numbers and there's no reason to use "romver" other than (decades of) momentum.

What does a "romver" really tell a user? "A number incremented from the last time you used this software." That's about it. It doesn't tell the user anything about what new features might have been added or bugs fixed or anything they actually care about. You can get a lot of the basic "number incremented" gut feeling simply from "Release Date", and that at least is something slightly more user concrete because they can look at a calendar and get a feel for how old a version is or how long between two versions development took, which is slightly more interesting.

Really though, "romver" itself is often just as meaningfully useful to users as "random fuzzy animal" or "random sugar snack" keywords, and those are at least more "fun". We can market software versions with other things than dotted sets of maybe sequential numbers.

It's not a battle I often win though, but it is something to think about. Numbers are great for machines, but they aren't very human, and why bother presenting numbers to people?


It's a good point. It really depends on who your users are. The "users" of my apps who would ever see the version numbers are people who need to know version numbers, and romver works fine for that. The actual end consumers of the software don't see version numbers because, like you said, it doesn't matter.

It does bother me that Apple and Google force you to have version numbers shown in their app stores and it's shown to the public. I push OTA updates for my apps quite frequently without going through the stores and I've had some users ask why the app changed without the store version number changing, and I've had users ask why the number jumped from 1.0.7 to 1.3.4 with no updates in between. "Because I didn't have to submit updates to the store for the past two minor changes but I've updated the app icon so now I have to" is difficult to explain to say the least.


This is how software was released up until the late 90s / early 2000s. It's nice for users and system administrators, but it solves a different problem than SemVer is intended to solve (API compatibility).


I agree (mostly). Here's my proposal:

https://gitlab.com/bshanks/sdver

{marketing}v{major}.{patch}

that is, there is no longer any number which distinguishes (non-breaking changes which add API) functionality from (non-breaking changes which do not).

The other main change in my proposal is a restriction of all numbers to be less than 32768, and a restriction of the length of strings. This allows compliant implementations to use fixed-size variable types.


The key value in minor, based on my understanding, is that it's unsafe for a package manager to automatically downgrade a package that was developed against a particular minor version because that would constitute removed functionality.


Are you bemoaning the lack of backward incompatible changes, or the lack of major version numbers because it feels like progress?


Some people just want a leading version number that they can spin manually.

For example, the creator of Backbone: https://github.com/jashkenas/backbone/issues/2888#issuecomme...

I say: why not both.


I'm not bemoaning anything, mate. I'm saying other people bemoan it. If you want to know why you'll have to ask them.


No problem. It remains unclear how other people not wanting to increment a major version is SemVer’s key flaw. Perhaps you could have worded that better?


If people don't want to use SemVer because they don't like incrementing the major component then that's a fundamental flaw. There's no point in it if it's not being used.

There's already a few examples of people's attitudes in sibling comments.

> Perhaps you could have worded that better?

That's a bit snide.


> That's a bit snide.

I've tried twice now to better understand what you're trying to say. In neither case have I been derogatory, mocking, or negative in intent or wording. Yet both times, you seem to have taken offense. You do you, mate, but it is immensely unhelpful to clarifying your point to someone who wanted to understand it.


I think the main issue is that there is no real semantics when incrementing the major version and no word about deprecation.

And BTW, in case of Java since 9, it's the opposite, each new version is a major version.


Here's a flaw I'd love to see fixed (2013) https://github.com/semver/semver/issues/145

Issues with delimiters in release versions on Linux




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: