[HN Gopher] Semver doesn't mean major.minor.patch, it means fail...
       ___________________________________________________________________
        
       Semver doesn't mean major.minor.patch, it means fails.features.bugs
        
       Author : Tomte
       Score  : 239 points
       Date   : 2021-08-06 16:20 UTC (6 hours ago)
        
 (HTM) web link (twitter.com)
 (TXT) w3m dump (twitter.com)
        
       | tedajax wrote:
       | What an abysmal mindset.
        
         | chomp wrote:
         | Can you explain why you don't like this?
        
         | 3np wrote:
         | How so? It's precisely as intended. Here's thesemver summary:
         | 
         | 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, and         PATCH version when you make
         | backwards compatible bug fixes.
         | 
         | https://semver.org/
        
           | one_off_comment wrote:
           | I'm not tedajax, but my guess as to what they meant is that
           | it's an abysmal mindset to think that making a breaking
           | change to an API means that the previous API was wrong. And I
           | tend to agree. Needs and assumptions change and sometimes
           | that means your API needs to adapt in a backwards-
           | incompatible way. That doesn't mean your previous API was
           | wrong for what it was built for. It just means it's wrong for
           | the new expectations.
           | 
           | I agree with tedajax that looking at any breaking changes as
           | a failure is a pessimistic, fatalistic, harmful viewpoint...
           | assuming that's what tedajax had in mind.
        
             | tedajax wrote:
             | Yeah that's pretty much what I had in mind.
             | 
             | I'd add further that more than likely once your API became
             | something usable new use-cases and ideas came up. I
             | wouldn't call major version numbers "failures" but
             | "evolutions".
             | 
             | The context of your project changing over the years
             | requiring breaking API changes is good and healthy.
        
             | simonw wrote:
             | The API was wrong. If you were an omniscient being with
             | complete understanding of the future when you designed it,
             | you would have known that.
        
               | 3np wrote:
               | Not necessarily. See my comment above. Needs change.
               | Breaking an API can be reasonable to accommodate for
               | that. It does not mean the past decision was incorrect
               | even with current knowledge.
        
               | simonw wrote:
               | That's my point: "Needs change". If you were a
               | supernatural omniscient being with full knowledge of all
               | possible pasts and futures you would have predicted that
               | need.
               | 
               | Since none of us are omniscient it's OK for us not to
               | build the perfect API the first time round!
        
               | 3np wrote:
               | Maybe I'm building my API for the users and use-cases for
               | today and next year, intentionally not accommodating for
               | those in 10 years. Those will be addressed in an upcoming
               | breaking release at some point until then. This can be a
               | sane decision even if you have full knowledge of what's
               | coming.
        
             | 3np wrote:
             | "Fail" is an overloaded word.
             | 
             | The new version fails under the previous versions API. That
             | doesn't mean that there is anything wrong with either old
             | or new release or API, just that there are breaking API
             | changes and it should not be considered a drop-in upgrade
             | before properly reading through release notes.
             | 
             | There's no implication of failure. Like you say, it
             | happens.
        
               | Stampo00 wrote:
               | The tweet literally says:
               | 
               | > _The thing about semver major version numbers are that
               | they don 't mean new stuff, they're a permanent reminder
               | of how many times you got the API wrong._
        
       | m0llusk wrote:
       | Posting on Twitter is a red flag indicating the author has a weak
       | grasp of the material and nothing significant to contribute.
        
       | 0xbadcafebee wrote:
       | This is literally the only tweet I've ever seen posted to HN that
       | was worth upvoting. It's not an entire book spread over 200
       | posts, it's just one nugget of useful info
        
       | treesknees wrote:
       | At my previous employer, we ended up handing over our versioning
       | to the marketing/business teams and our development teams started
       | using a semver-style internally recognized release number for
       | tracking features and fixes. Too often our customers would demand
       | a new feature/driver/interface in a .PATCH or .MINOR release in
       | order to more quickly adopt the software without having to run
       | through their internal qualifications and upgrade policies.
        
         | happytoexplain wrote:
         | Yup. We use code names for products internally for the same
         | reason. Never use a user-facing value as an identifier, as
         | obnoxious as trying to adhere to that can be.
        
       | bryanmikaelian wrote:
       | Reminds me of the talk Rich Hickey gave about Clojure Spec and
       | why semver fails.
       | 
       | https://youtu.be/oyLBGkS5ICk
        
       | jka wrote:
       | In an imaginary world that is not very much like our current
       | world of software development, there are no version numbers at
       | all - only commit references.
       | 
       | You generally want to upgrade to the latest high-quality commit
       | reference available, by following an upgrade path from the commit
       | your application is currently deployed from.
       | 
       | Breaking changes can be identified automatically using static
       | analysis of the commits thanks to language-level support and/or
       | well-defined interface definitions.
       | 
       | For all of the important workflows you use, you have external
       | integration tests, so you can navigate the commit-space (and
       | potentially even merge multiple paths) fairly arbitrarily with
       | some degree of both statistical (test coverage, performance) and
       | qualitative (feature support, hardware compatibility) confidence.
        
       | mjw1007 wrote:
       | Using semver is a promise that if you make a backwards-
       | incompatible change you will update the major version.
       | 
       | That's entirely separate from any promise, or statement of
       | intent, that you might want to make about whether you're hoping
       | to make backwards-incompatible changes rarely or frequently.
       | 
       | Teaching people that they should consider incrementing the major
       | version as indicating a failure isn't going to be helpful.
       | 
       | In practice, given the way semver is defined, if this idea
       | catches on I fear the main effect will be to increase the number
       | of projects that never choose to declare they're version 1.0.
        
         | mjw1007 wrote:
         | More concretely, scrolling up I see that the tweeter says their
         | threshold for declaring 1.0 is when they << feel that the API
         | will only need to be extended in a backwards compatible way.
         | When taking care not to break people's code is not a burden. >>
         | 
         | I don't think that's the general understanding we should be
         | aiming for.
         | 
         | Rather I think a better threshold (and the one implicit in
         | semver's definition) is to declare 1.0 when the API is stable
         | enough that you're willing to go to the effort of tracking
         | whether the changes you're making are backwards-compatible.
         | 
         | Otherwise we're discarding useful information in the meantime.
        
           | simonw wrote:
           | So in your model 1.0 is the point at which you start writing
           | proper release notes?
           | 
           | I'm not keen on that. During my 0.x period I still want
           | interested third parties to try out and use my code, which
           | means I need to give them good release information to help
           | them help me test everything out.
        
             | mjw1007 wrote:
             | You can start writing release notes any time you like.
             | 
             | The idea of semver was that you use the version number to
             | encode compatibility information, and stop using it as a
             | vague indication of the maturity of the project or the size
             | of the changes in a particular release.
        
       | dmitriid wrote:
       | I strongly encourage people to use ComVer instead:
       | https://gitlab.com/staltz/comver
       | 
       | It's <BREAKING CHANGES>.<100% BACKWARDS COMPATIBLE CHANGES>
       | 
       | That's it. Fully SemVer compatible, if you want (just add .0 at
       | the end)
        
       | andrew_ wrote:
       | > they're a permanent reminder of how many times you got the API
       | wrong
       | 
       | I'd agree in part with this sentiment only for the last segment:
       | PATCH. Otherwise, unless you're just producing a mountain of
       | garbage on a routine basis, they're more an indicator of
       | _improvements_ in an API or a versioned thing.
       | 
       | As it goes with Twitter, the tweet author didn't provide nearly
       | enough nuance to justify the statement.
        
         | one_off_comment wrote:
         | You're correct. As usual, the truth lies somewhere in between
         | the two extremes.
         | 
         | People seem to really hate the gray area despite the fact the
         | most of life lies in it.
        
           | BoorishBears wrote:
           | They don't hate the gray area, they pretend to hate the gray
           | area because the gray area doesn't get you on the front page
           | of HN
        
             | 0des wrote:
             | Is there a word for this level of meta-analysis?
        
               | YawningAngel wrote:
               | Cynicism, perhaps?
        
               | BoorishBears wrote:
               | I prefer realism.
               | 
               | I mean just read the tweet again, but ignore the zingy
               | psuedo-snowclone X.Y.Z
               | 
               | If someone told you "every breaking change to your API is
               | a failure", would you give them the time of day?
               | 
               | But repackage that frankly useless opinion in a zinger
               | and suddenly you have people spending hundreds of
               | comments slowly working backwards to a more nuanced
               | commentary that no longer has anything to do with the
               | original point...
               | 
               | -
               | 
               | Seriously look at their reply:
               | 
               | > I'm watching with amusement as this tweet spreads and
               | it turns out a decent proportion of people are finding it
               | really offensive - feels like people are OK with learning
               | from their mistakes but not with learning from their
               | failures
               | 
               | ... what?
               | 
               | Because people don't agree with your "hot take" that
               | breaking changes are a failure, they... are ok with
               | making mistakes. But also not ok with failure.
               | 
               | Pass me a little bit of whatever it took to make this
               | seem profound?
               | 
               | -
               | 
               | Why do we give this kind of drivel room? Why give the
               | time of day to an opinion so bad that you need to have a
               | 10 level deep conversation to come up with something
               | resembling a useful take from it?
               | 
               | I guess because we're bored?
        
         | simonw wrote:
         | Surely the minor version number (FEATURE) in this model is the
         | indicator of improvements to the versioned thing?
        
       | rolha-capoeira wrote:
       | "How many times you got the API wrong"? I get the concept, and
       | maybe it's correct some of the time... but it ignores the vast
       | majority of software releases over time, which are evolved
       | products/projects. What I initially set out to do != what's
       | valuable/useful to the world.
        
         | simonw wrote:
         | So you got the API wrong - because you didn't have omniscience
         | about every possible problem your code would need to solve in
         | the future.
         | 
         | There's no shame in admitting that with a major version bump.
         | None of us are infallible.
        
           | rgoulter wrote:
           | This makes me wonder what the largest MAJOR in
           | MAJOR.MINOR.PATCH exists in the wild.
        
       | ajmurmann wrote:
       | I find this framing to be too inward looking. SemVer isn't for me
       | as the library developer, it's for users of my library. What it
       | really means in that context for most users/customers outside of
       | toy projects is:
       | 
       | EXPENSIVE-HIGH-RISK-UPGRADE. MEDIUM-RISK.LOW-RISK
       | 
       | There is a carrot-side to this but that usually only matters in
       | specific cases for a subset of users.
       | 
       | EDIT: one small practical addition: If you are fixing a big that
       | requires very large changes to how things work at a more
       | fundamental level, I'd at least think twice about shipping that
       | in a patch. While it technically fits the definition of SemVer,
       | it might violate implicit expectations of users who are using
       | your library in production. The change really needs to carry its
       | weight.
        
         | neilv wrote:
         | The PLaneT network package manager did it even simpler:
         | APIBREAKING.NONAPIBREAKING. Which might be interpreted as
         | NEEDSENGINEERINGLOOKBEFOREUPGRADE.SAFEAUTOUPGRADE.
         | 
         | This was used for PLT Scheme, and was a rather nice 90%+ very
         | lightweight solution.
         | 
         | If you were doing a package where backward-compatibility was a
         | very high priority, you might be at PLaneT version 1.x forever.
         | 
         | If you were doing rapidly evolving research, and wanting to
         | share code, while not surprise-breaking people who might use
         | your stuff, you could end up with a large major version. For
         | example, a package by Dave Herman (of Mozilla and Rust fame)
         | got up to 9.x in only 2 years. http://planet.racket-
         | lang.org/display.ss?package=javascript....
         | 
         | I don't recall whether anyone ever encountered unexpected
         | breaking changes in practice that the version number didn't
         | indicate. I'd guess probably. It wasn't a 100% solution alone.
         | 
         | PLaneT also supported specifying in a code file import which
         | versions of the package you were known to work with (like
         | meaning "major version 4, with minor version 2 or later; or
         | major version 5"), with automatic installation of those.
         | 
         | You could also mix multiple versions of a package in a system,
         | in the normal case (though maybe not if you had something like
         | singleton state or resource that multiple versions of the
         | package wanted to control). This seemed very valuable for
         | pulling in lots of small open source dependencies, directly and
         | indirectly, from different developers.
         | 
         | One downside of this simple approach is that it's bad as a
         | "marketing version number". Like if you wanted to convey the
         | value of large new features (or maybe talk about them in an
         | easy way, like "version 4 foo features"), but you've been
         | sticking to version 1.x backward compatibility the whole time.
         | So there was a separate marketing version number, which seemed
         | confusing enough that there must be a better way. But it was at
         | least 90% there.
        
           | ajmurmann wrote:
           | I think the difference between minors that include non-stop
           | breaking features and patches actually is important. If you
           | run a mission-critical system you want to minimize risk as
           | much as possible but also get your needed fixes, especially
           | if they are for CVEs. If it was a fair assumption that we
           | only ever break things on purpose the PLaneT versions would
           | be totally sufficient though.
        
             | neilv wrote:
             | Good point. If we had something PLaneT-like, I wonder this-
             | is-important-security-fix should be included in the version
             | number (maybe a big `S` suffix), or separate. Or whether it
             | much matters.
             | 
             | Security fixes are exceptional situations, requiring
             | scrutiny from developers and also sometimes by end users.
             | To understand the implications, what's affected, the
             | urgency, any other impact, etc.
             | 
             | And we also have situations like a popular distro often
             | shipping regressions in their security updates (including a
             | "bricking" one for some hardware platforms last year, which
             | threatened some appliances I had installed overseas).
             | 
             | Given this need for scrutiny by at least developers, I
             | don't know whether having is-a-security-update information
             | in the version number itself helps, or is just as well (or
             | better) represented separately.
             | 
             | One distinction that might be intuitive and relevant... We
             | already know that is-backward-compatible-with-previous-
             | version(s) is something that could be handled more flexibly
             | separate from the version number, such as for updating
             | changing knowledge about that after a version release --
             | _but_ there 's lightweight benefits to being able to talk
             | about that in a version number, such as in the import line.
             | But the import line doesn't need to talk about security
             | update handling, and probably shouldn't.
        
         | mrits wrote:
         | MARKETING.PM.ENG is closer to my experience
        
           | ithkuil wrote:
           | Somebody should come up with a name for this and craft a
           | manifesto on a website :-)
           | 
           | Realver.org? Enterprisever? Corpver?
        
             | dlor wrote:
             | Hah! I had something similar awhile ago:
             | https://twitter.com/lorenc_dan/status/1209289792569131008
        
               | BeefySwain wrote:
               | I particularly love your followup:
               | https://twitter.com/lorenc_dan/status/1209290259386769408
        
         | simonw wrote:
         | I see the middle number as "RISK-FREE-UPGRADE" - if I bump that
         | number in one of my packages it means there's a new feature,
         | which should have no impact at all on existing code.
        
           | marcosdumay wrote:
           | That's because you are a library author, and because you are
           | following the standard.
           | 
           | A library user can't afford to assume any change is risk-
           | free. Even when the author claims it is.
        
         | andrew_ wrote:
         | I like the thought process here.
         | 
         | In theory MINOR and PATCH are both supposed to be low risk. The
         | risk only increases if the developer/process in control of the
         | versioning doesn't recognize when a fix or feature contains a
         | breaking change.
        
         | thrashh wrote:
         | This is how I handle my libraries too. My standard is that you
         | will never have a breaking change in any of my minor or patch
         | versions.
         | 
         | I may ship new API in minor versions, and if I need to do an
         | API rewrite, there will be a few years where you can use both
         | APIs, then in a future major version, I will deprecate the old
         | API (emit warnings), then in yet another future major version,
         | I will finally remove the old API.
         | 
         | Basically my expectation is that if you use my library, you're
         | set. You'll get new features with minimal stress.
        
         | eurasiantiger wrote:
         | More like NEED-REFACTOR.CHECK-TODOS.CHECK-FIXMES
        
         | [deleted]
        
         | cogman10 wrote:
         | At this point, I feel like the version numbering of semi-ver
         | has lost all meaning.
         | 
         | I've been broken by every level of version bump. I've seen APIs
         | that went from 1.0 -> 2.0 and really were only backwards
         | incompatible because of a single method change.
         | 
         | I've seen countless major changes to method signatures from a
         | 1.0 -> 1.1 bump.
         | 
         | I've even seen breaking API changes from a 1.0.0 -> 1.0.1 bump.
         | 
         | It seems like everyone has a different feeling on when those
         | numbers should be rolled. That inconsistency makes it
         | impossible really understand what an upgrade is going to do
         | without tests.
        
           | kodah wrote:
           | I think some of this is because even package maintainers have
           | a hard time deciphering what is potentially "breaking". There
           | was a great talk at GopherCon about an ambitious project
           | whose goal was to be able to detect if you made backwards
           | incompatible changes, which on the facade seems easy (to some
           | folks, apparently) but is in fact not.
        
             | notJim wrote:
             | That's funny, because on the face of it, detecting breaking
             | changes seems impossible to me, not easy.
        
               | kodah wrote:
               | I remember the speaker going pretty in depth on "what
               | looks obvious" vs "bet you didn't know this changes
               | behavior".
               | 
               | That said, my sentiment is the same as yours. I was
               | surprised that even needed addressing.
        
           | paulddraper wrote:
           | Because in reality _every_ change is breaking to someone.
           | Some just break more stuff than others.
           | 
           | No software story is more classic than the bugfix breakage.
           | _There is a reason versions are pinned. There is a reason
           | lockfiles exist._
           | 
           | ---
           | 
           | Whatever your intentions, versioning is HIGH.MEDIUM.LOW
           | breakage.
           | 
           | I don't degenerate versioning at all; I find it to be very
           | helpful. But don't pretend it guarantees something that it
           | can't.
           | 
           | Versioning is simply a best-effort communication of risk.
        
           | kbenson wrote:
           | Not every project follows semver. Just because there are
           | numbers with periods interspersed doesn't mean it's semantic
           | versioning. People have been throwing numbers together to
           | communicate _something_ about what it is for a long time now,
           | long before semantic versioning was formalized.
        
             | cogman10 wrote:
             | Which is exactly the point I'm making.
             | 
             | Semver only really works if everyone, or most everyone, is
             | following it.
             | 
             | There are a lot of build tools that make that assumption.
             | (cargo, npm, gradle, pip, for example).
             | 
             | Without that, you end up needing to have very deep
             | understandings of your dependencies and their
             | subdependencies. Otherwise, it's impossible to know what
             | will happen when you update something.
        
               | volta83 wrote:
               | This is funny because everybody makes mistakes , so of
               | course people fail at semver.
               | 
               | However, if you are the maintainer of a popular cargo
               | package, and make a mistake, people _will let you know_.
               | Because a lot of people in the Rust ecosystem expect
               | versions to follow semver.
               | 
               | Crates that fail to adhere stop being used, get bad rep,
               | people fork them, and keep them stable, making them loose
               | users.
               | 
               | Rust actually has a tool called rust-semverver that does
               | an AST to AST diff of the current version of a crate that
               | you want to release, with the latest release, and
               | suggests how to increment the version.
               | 
               | It can list all API changes, and it will tell you which
               | changes are minor, major, or patch.
               | 
               | You can use it in your deployment workflow on CI to,
               | e.g., deploy a new version of a crate only if, the
               | changes follow the version change that was specified.
               | Such that, e.g., if you bump your 2.0.0 crate to 2.1.0
               | but your crate has an API breaking change, the tool and
               | CI fails telling you that you need to change the version
               | to 3.0.0 because of these changes.
        
               | azernik wrote:
               | It doesn't need everyone to follow it; it just needs
               | library maintainers to declare when they do follow it,
               | actually mean it when they do, and check their own
               | dependencies for breaking changes.
               | 
               | ie a library that declares it uses semver should create
               | an abstraction barrier around all of its dependencies,
               | such that the user should only need to care about
               | declared breakages in their direct dependencies.
        
               | kbenson wrote:
               | I get more what you're trying to say now. To some degree,
               | some people are definitely failing to adhere to semver
               | when they're part of a larger ecosystem that needs it,
               | like the ones you mentioned. Regardless of what
               | versioning a module uses internally for development, they
               | should be exposing a good semver compatible version to
               | the tooling that uses them that expects it, but they
               | often fail in this.
               | 
               | There is, alternatively, likely some assumption at this
               | point in end users that some random project on github or
               | elsewhere might be following semver even if they haven't
               | stated as much, and without a stated intention to follow
               | semver by the project and showing that they are willing
               | to do so that means little and is a poor assumption.
               | That's not necessarily applicable to your original point
               | though.
        
       | profmonocle wrote:
       | In the Node.js ecosystem, major semver bumps often just mean that
       | support for an EOL version of Node was dropped. Which is a good
       | thing IMO - allows the devs to use modern JS conventions without
       | as much transpiling overhead.
        
       | didibus wrote:
       | BREAKING.FEATURES.BUGS
       | 
       | I think would be better. And when you look at it that way,
       | BREAKING could be in order to provide new features that
       | necissated breaking changes, or it could be because the old way
       | sucked and nobody liked it, or any other reason, but the version
       | bump communicates that the changes are breaking backwards
       | compatibility in some known way.
       | 
       | As an aside, this is why some people say SemVer is bad, because
       | ideally a dependency should never be breaking you.
       | 
       | An alternative to SemVer is to do:
       | 
       | FEATURES.BUGS and simply never push breaking changes.
       | 
       | So what if you want to make some changes that mandates breaking
       | compatibility?
       | 
       | Well you simply release a new library or framework under a new
       | name.
       | 
       | That way the name of a dependency is a 1:1 correspondence with
       | its exact interface. If the interface changes in breaking ways
       | it's a new dependency.
       | 
       | This also allows you to then depend on both, possibly even
       | letting you transition from one to the other in phases.
        
         | lolinder wrote:
         | > So what if you want to make some changes that mandates
         | breaking compatibility?
         | 
         | > Well you simply release a new library or framework under a
         | new name.
         | 
         | I don't think that's necessary. If you use the model you
         | propose (BREAKING.FEATURES.BUGS) and steer _very_ clear of
         | breaking changes until absolutely necessary, then  "Framework
         | 2" becomes in a very real sense a new product while still
         | conveying continuity of development team, ideas, etc.
         | 
         | I think of Vue 3, Python 3, Bootstrap 5, or Fontawesome 6. No
         | one would make the mistake of thinking they could just update
         | the version number and be on their merry way. They're treated
         | as "new dependencies", in effect, but re-using the name makes
         | it still obvious that it's the same team and philosophy behind
         | the new language/framework.
         | 
         | One aspect of each of the projects I list above is the
         | continued commitment to maintenance on the old versions, with
         | security and bugfixes and with the old documentation still
         | being available for years after the new version is out. This
         | allows organizations to treat the new major version as a new
         | dependency, with all the caution that entails, without fear of
         | having the rug yanked out from under them.
        
           | travisjungroth wrote:
           | After thinking about this topic too much, I've come to the
           | same answer you have except you've said it better. (Although
           | I disagree on people not thinking they can upgrade majors no
           | problem. That for sure happens).
           | 
           | If you think every breaking change should have a new name, as
           | the person above you does and I've heard come out of the
           | Clojure community, then just append the major version number
           | to the product name in your head. Otherwise, what do you
           | expect them to name it? A name that kinda reminds people of
           | the first one? If it's mostly the same group of people
           | solving mostly the same problem in mostly the same way at a
           | later point in time, NAME N -> NAME N+1 captures that better
           | than anything else.
           | 
           | For all the shit we give the Python 2 to 3 upgrade (and they
           | give themselves) I have never heard an alternative that I
           | really find satisfying. It seems the problem was: We want to
           | stop working for free on this old stuff we don't like any
           | more. We want to keep the name, the websites and t-shirts
           | since we own them and we're doing almost the same thing.
           | Every answer I hear wants the people working for free to give
           | up one of those reasonable things.
        
           | paulddraper wrote:
           | Yeah, but what Chrome/Firefox version are you using?
        
       | pipework wrote:
       | 0. Time since last Intentional-Breakage/Funding-round.
       | 
       | 1. "Features" released since last Intentional-Breakage.
       | 
       | 2. Acknowledged mistakes since last "feature" release.
       | 
       | 3. Scuff-ups since last mistake or "feature".
       | 
       | 4. Comical 'release name' to distract management from size of
       | last two numbers.
       | 
       | 0.1.2-3-haffagudtay
        
       | greggyb wrote:
       | There's a really good Rich Hickey talk about versioning. Agree or
       | not, it's a great prompt for considering what you want from
       | versioning.
       | 
       | https://www.youtube.com/watch?v=oyLBGkS5ICk
        
       | tialaramex wrote:
       | I don't buy that the need to bump Major is a failure.
       | 
       | This is _particularly_ true if you continue to maintain the
       | previous major version to the same degree (if any) that you
       | maintain the new one, and _especially_ true if you have an
       | explicit release lifetime strategy.
       | 
       | If I tell you that misfortunate 1.x will be actively seeing new
       | work until 2025 and then bug fixes until 2028, and I deliver,
       | misfortunate 2.x doesn't break that promise. Maybe you wish a new
       | feature from misfortunate 2.6 could have been in 1.34 instead,
       | but too bad I never promised that and most likely the way I did
       | it would be incompatible with 1.34 anyway.
       | 
       | I also think that people underestimate how bad bugs can be.
       | Sometimes the _minimum_ fix is a breaking change.
        
       | qzw wrote:
       | So Chrome has had 92 fails and around 70% of the browser market.
       | Guess I'm not failing enough then.
       | 
       | [edit] Yes, I missed the semver part of the tweet. This is why
       | I'm not on twitter, and should stay out of these threads in the
       | future.
        
         | simonw wrote:
         | Chrome doesn't use SemVer.
        
           | tobyjsullivan wrote:
           | Maybe not technically semver but it seems close enough for
           | the joke to hold.
           | 
           | https://www.chromium.org/developers/version-numbers
        
       | 3np wrote:
       | To anyone who think they disagree: The tweet is not really an
       | opinion or a hot take, just a rephrasing of the semantics (you
       | know, the sem in semver). Read "Fails" as verb and not plural
       | noun and it makes sense.                 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, and
       | PATCH version when you make backwards compatible bug fixes.
       | 
       | https://semver.org/
       | 
       | The idea is that users can get expectations right when assessing
       | an upgrade and plan accordingly. If you don't follow this, you're
       | not doing semver.
        
       | JamesSwift wrote:
       | Should I read the release notes in depth?
       | 
       | DEFINITELY.PROBABLY.POSSIBLY
        
       | karmakaze wrote:
       | If those are the axes, then it should really be
       | fails.bugs.features since new features can be safely added but
       | changing an existing function which had a 'bug' can be
       | unpredictable.
        
       | crazygringo wrote:
       | > _they 're a permanent reminder of how many times you got the
       | API wrong._
       | 
       | I mean, that's clever for a tweet, but I hope nobody takes that
       | seriously.
       | 
       | It's pretty counterproductive to view design through the lens of
       | getting something wrong or right. There's just iteration in the
       | direction of improvement. It didn't start out wrong -- it was
       | your best first attempt with what you knew at the time. Then you
       | learned more and so it improved. But it'll never be "right", just
       | incrementally "more useful".
       | 
       | API's aren't mathematical proofs.
       | 
       | Just in case anyone needs to hear it ;)
        
         | matttrotter wrote:
         | Amen. Although, if you're on version 931.59.12, then maybe
         | something is wrong.
        
           | jdauriemma wrote:
           | Almost an IP address
        
         | simonw wrote:
         | I wonder if people would be less offended by this if it was
         | "MISTAKES.FEATURES.BUGS".
         | 
         | In American culture (in my experience) everyone takes pride in
         | learning from their mistakes - but no-one likes to think of
         | them as failures.
        
           | andrew_ wrote:
           | I'm not offended. I just think it's wrong to paint with such
           | a wide brush. Breaking changes don't always mean that
           | something was a mistake. They often mean a change in
           | direction, and that can happen for a myriad of reasons.
           | 
           | We like more nuance on HN than Twitter seems to.
        
             | edgyquant wrote:
             | Seems like it has to do with the word failure more than
             | anything. It is a failure, every time you don't ship a
             | perfect product it's a failure of some kind. The iteration
             | process is simply removing failures from a product until
             | you reach feature completeness. I don't think the
             | difference is that large between a failure and a mistake.
        
               | vangelis wrote:
               | This is definitely true for library code. I don't think
               | the idea holds up for squishier things- moving from
               | version 1.x to 2.x could make the user experience worse,
               | depending on what you prioritize and who's making
               | decisions.
        
               | kbenson wrote:
               | > It is a failure, every time you don't ship a perfect
               | product it's a failure of some kind.
               | 
               | It's impossible to ship a perfect product. So perhaps we
               | shouldn't use "failure" to denote not doing the
               | impossible, and reserve it for cases where "success" is
               | even possible.
        
               | simonw wrote:
               | This thread has made me appreciate the Star Trek
               | Kobayashi Maru exercise in new ways. People _really_
               | don't like being told that they've failed.
        
               | andrew_ wrote:
               | Perhaps the approach of vapid, pessimistic short-takes
               | doesn't play well outside of Twitter, where folks aren't
               | as impressed by blue checks and large followings, and
               | where there isn't a benefit to jockeying for engagement.
               | Based on your comments throughout the threads here, you
               | appear to be overly eager to paint with an overly
               | negative, wide brush that ignores nuance and the
               | multitudes of situations in which your assertion doesn't
               | come close to being true. For instance, adopting an
               | upstream dependency change containing a breaking change,
               | which necessitates releasing a major version in which no
               | notion of failure, mistake, or misstep exists. I'm unsure
               | how you gained such a large following, but your comments
               | aren't at all inspiring or insightful - only somewhat
               | controversial.
        
               | ecnahc515 wrote:
               | It's possible to ship a product that doesn't break
               | though.
               | 
               | You can add new APIs, etc, instead of breaking existing
               | ones. Anytime you do a major rev because your changing an
               | API or removing one, you could also ship new APIs instead
               | and keep the major version the same.
        
               | andrew_ wrote:
               | I don't believe that a prior thing which lacks a new
               | advancement means the prior was a mistake or a failure.
               | We're a creative species that strives for improvement.
               | The first running shoe wasn't a mistake nor was it a
               | failure. But the ones I use to run 40 years later sure
               | have improvements.
        
               | edgyquant wrote:
               | That's why I don't think failure is a good word. But
               | what's a word to say, "it works but it could be better,"
               | other than failure?
        
               | jaredklewis wrote:
               | Even if did ship a perfect product, it wouldn't stay
               | perfect because the world changes.
               | 
               | Which is why I think it is bad semantics to say changing
               | an API is an indication of failure.
        
             | SilasX wrote:
             | In practice, usually it means "we couldn't think of a way
             | to do this without breaking changes even though ways
             | clearly exist".
        
           | 3np wrote:
           | As I mentioned below, "fail" is an overloaded word and in
           | server another meaning is intended. Longer but more correct:
           | "BREAKING_CHANGES.FEATURES.BUG_FIXES"
           | 
           | You can get everything right and still intentionally
           | introduce a breaking change in a future release.
        
           | secondcoming wrote:
           | Maybe the 'offence' is from somebody reading far too much
           | into something?
        
           | simonw wrote:
           | Will is now suggesting "LEARNING_OPPORTUNITIES.FEATURES.BUGS"
        
           | Lendal wrote:
           | True. Many people get offended when you say the glass is half
           | empty, but nobody gets offended when you say the glass is
           | half full. If I must point out a failure, I will make sure to
           | wink and smile while doing it, which is tough on Twitter.
        
           | Macha wrote:
           | Is something that can be improved inherently a mistake?
           | 
           | Mistake/Failure both imply an extra level of judgement "Oh,
           | if only you'd worked harder you would have had the right API
           | design the first time and you'd never need a new version".
           | 
           | Sometimes the world changes around an API.
           | 
           | Sometimes there is data that can only be gathered from real
           | world usage.
           | 
           | Sometimes there's new use cases to handle.
        
           | inanutshellus wrote:
           | If one is desperate for a "fails/mistakes" kind of verb then
           | "BREAKS" (as in "includes breaking changes") might actually
           | hold sway, but then you'd leave out the "major functionality
           | added" scenario for, well, MAJOR.
           | 
           | In short, I think OP's observation is that of a pessimist's.
           | 
           | If not "MAJOR.MINOR.BUG" (which needs no improvement IMO) I'd
           | go with...
           | 
           | TECTONIC.FEATURE.FIX.
        
           | stonemetal12 wrote:
           | Opengl jumped from 2 to 3 because hardware changed. It
           | doesn't mean the old API failed or was a mistake, it did the
           | job it was intended to do, and then they needed it to do
           | something radically different.
        
             | jfrunyon wrote:
             | They failed to predict the future hardware.
             | 
             | A failure isn't always a bad thing. Sometimes it's the best
             | thing possible.
        
               | seoaeu wrote:
               | Predicting the future wasn't the objective. The hardware
               | of that time couldn't have supported OpenGL 3 even if
               | they'd wanted to
        
               | Macha wrote:
               | Stating that they failed to predict the future hardware
               | implies that they should or could have.
               | 
               | Is this true? Maybe, maybe not, I'm neither a GPU driver
               | write or a hardware writer, but I suspect no software
               | writer in 1997 was going to predict the hardware of 2008.
        
               | ratww wrote:
               | Actually they didn't. It was still backwards compatible,
               | so the number change would be unnecessary in semver.
        
             | badsectoracula wrote:
             | OpenGL 3 is backwards compatible with 2 itself being
             | backwards compatible with 1, etc. (ignoring the whole
             | profiles thing which was a mistake and aside from Apple who
             | went their own way with Metal, everyone else eventually
             | agreed with that) as is 4.
             | 
             | Also OpenGL 1.x didn't map to the underlying hardware even
             | considering SGI, a lot of stuff was done on the CPU. The
             | only time OpenGL matched the underlying hardware was around
             | GeForce 2 and AFAIK that was really matching Nvidia's
             | hardware - before and after that little window, OpenGL was
             | its own abstraction.
             | 
             | But of course OpenGL is a very good example of an API done
             | right (especially before Khronos took over and made a mess
             | out of it): it did a reasonably good prediction for the
             | future while providing a good API for the present (at the
             | time) and even when the underlying hardware changed
             | considerably, it still remains a very useful API with a
             | reasonable mapping and its extension system allows it to
             | take advantage of new hardware features without breaking
             | existing code.
             | 
             | While i do not think Khronos did a good job on OpenGL, at
             | least they did the right thing by making Vulkan a separate
             | API instead of calling it "OpenGL 5", allowing the two APIs
             | to coexist and not break any existing code. After all
             | Vulkan is fine (even if not to my taste, it is
             | unnecessarily oververbose and pretends to be a low level
             | API when it isn't) if you absolutely want the best
             | performance from a hardware abstraction API while OpenGL is
             | still around when you do not need that and want something
             | more user (programmer) friendly instead (though do not get
             | me wrong, depending on what you do, you can extract a lot
             | of performance out of OpenGL, though after some point you
             | may need to switch to Vulkan).
        
           | jayd16 wrote:
           | PAST-MISTAKES.FUTURE-MISTAKES.CURRENT-MISTAKES
        
             | theli0nheart wrote:
             | Nailed it.
             | 
             | Everything becomes a mistake eventually.
        
               | inanutshellus wrote:
               | "You[r feature] Either Die[s] A Hero, Or [it] Live[s]
               | Long Enough To See [it]self Become The Villain" ~Harvey
               | Dent [Sorta]
        
               | eurasiantiger wrote:
               | That's surprisingly applicable. I've definitely seen this
               | happen more than a few times.
        
             | simonw wrote:
             | Hah that's really good.
        
         | cratermoon wrote:
         | My first thought was along the same lines. Especially for the
         | major version, there's no need to imply there was a failure.
         | Version 1.0 was the right thing at the time. Version 2.0 means
         | something about the requirements or use cases _changed_ in the
         | intervening time, so it 's necessary to track that change.
         | Minor and Patch have the same implications, although in my mind
         | a "patch" can also happen when there's just the sort of mistake
         | the can creep in because of human imperfections.
         | 
         | In any case, it doesn't matter except to consumers of the API
         | who need to know the level of backward compatibility.
        
         | kall wrote:
         | Seeing a project on a pretty high major is a positive signal to
         | me. It tells me that they understand semver and know how to use
         | breaking changes. Of course if a project is just very stable
         | and sticks to 1.x, that's great too. I don't consider that a
         | negative signal. Purely anecdotally, 3 is the scariest version
         | number to me.
         | 
         | React sets a pretty good example here: react 17 is the most
         | boring release in the world. The react team are not bad API
         | designers that made 17 major mistakes. They may be the most
         | considerate and pleasant API designers in all of frontend,
         | actually.
         | 
         | React Native is on 0.64.4 (?) not because it's unfit for
         | production but because they know the level of guarantees they
         | can make about version upgrades is zero.
        
           | bpodgursky wrote:
           | I've also seen projects on like 124.0.0 just because they
           | don't care about semver and just release major versions every
           | time.
        
             | CJefferson wrote:
             | It's also easy to get to 124 if you are a library with very
             | few private functions -- in that case almost any change
             | breaks ABI.
        
             | eurasiantiger wrote:
             | Still a better release numbering scheme than going by year
             | and update.
        
             | nonameiguess wrote:
             | The Naval Research Lab releases their radar processing
             | algorithms package for geointelligence products by build
             | number. We always got a kick out of a new delivery updating
             | us from nrltools-3872 to nrltools-4923 or something.
        
           | travisjungroth wrote:
           | 2 seems to be the final number for business stuff.
           | CustomerReportv2 or UserModel2 or /api/v2/ are wildly more
           | common than 3 IME.
        
             | unilynx wrote:
             | "That major update where we redid the whole API turned out
             | to be so unexpected painful, we're never doing that again"
             | once for every business
        
           | dexterhaslem wrote:
           | yes but didn't react do a big jump? like 0.13 -> 14.0 or such
           | many moons ago. at any rate agree with the point
        
             | mcaruso wrote:
             | 0.x releases are also major versions according to semver,
             | just pre-stable. So many people were referring to React 0.x
             | releases as "React x" that they just bumped it straight to
             | version x.
        
           | kstenerud wrote:
           | Unfortunately, go has broken semver, so all of my go projects
           | now stay at 1.x.y, with x being the "major" version (breaking
           | changes) and y being the "minor" version (non-breaking
           | changes) and the 1 sitting there useless. I suspect that many
           | others do the same, so for go projects the x version field is
           | the one to pay attention to.
           | 
           | Although TBH it's not all bad; all anybody has ever really
           | cared about is "are there breaking changes or not?"
        
           | devin wrote:
           | To me it's a signal that if I rely on this software in my own
           | projects, I am signing up for an upgrade treadmill.
        
             | kyrofa wrote:
             | Amen.
        
       | dancemethis wrote:
       | Nah, it means "boring", "yawn" and "soulless".
        
       | dragonwriter wrote:
       | > Semver doesn't mean MAJOR.MINOR.PATCH, it means
       | FAILS.FEATURES.BUGS
       | 
       | It think I understand all the projects afraid to go to 1.0:
       | 
       | "0 fails"!
        
         | BenjiWiebe wrote:
         | My projects stay at 0.x because they never quit failing...
        
       | AnIdiotOnTheNet wrote:
       | If more developers had had this mindset, DLL hell might not have
       | ever been a thing.
        
         | shadowgovt wrote:
         | Oh, you can definitely get into DLL hell with semantically
         | versioned APIs. DLL hell is mostly a symptom of diamond
         | dependency problems... One library cares deeply about the
         | version of a dependency, a second library cares deeply about a
         | different version of the same dependency, and your code
         | requires both of those libraries.
        
       | simonw wrote:
       | I absolutely love this (I was part of this Twitter conversation).
       | 
       | My take on SemVer is that the ideal version number would be
       | something like 1.452 - 452 new feature release without ever
       | breaking backwards compatibility.
       | 
       | Almost impossible to actually achieve this, but it's good to be
       | ambitious!
       | 
       | Also: doing SemVer properly requires you to provide really good
       | documentation. A bug fix should correct an issue where actual
       | behavior differs from the documented behavior.
       | 
       | Without this, a "bug fix" is indistinguishable from a breaking
       | change.
        
         | neolog wrote:
         | Why break the existing library instead of making a new one?
         | Concretely, why not do like jinja2 and psycopg2?
        
           | OJFord wrote:
           | Because that's really annoying? Boto is (forever now,
           | presumably) v2.x, and Boto3 is on v1.x.
           | 
           | How is that helpful?
        
           | treesprite82 wrote:
           | No existing project should break unless its developers take
           | the action to upgrade (bumping the version of the library
           | that the library manager is looking for).
           | 
           | The reason I'd personally prefer package 2.0.0 rather than
           | package2 1.0.0 is because a lot of tools understand the
           | former. For example tools can let the user know a breaking
           | update is available, or allow me to specify that my project
           | works with many major releases of package, or
           | upgrade/downgrade more conveniently.
        
           | simonw wrote:
           | Because then you have to actively maintain two libraries
           | forever instead of one.
        
             | neolog wrote:
             | No I don't, I can always stop maintaining a library. But I
             | don't have to actively break it either.
        
               | simonw wrote:
               | In that case the maintainer can release version 2.0 and
               | have a note in the README that says "if you don't want
               | the breaking changes in 2.0 here's how to install the
               | last release from the 1.0 series - note that this series
               | is no longer maintained so any bugs or security issues
               | will not be addressed."
        
             | blacktriangle wrote:
             | That's the price of writing maintainable software.
        
             | ajmurmann wrote:
             | Two libraries or two branches. What's the difference?
        
           | crdrost wrote:
           | "So I spent a week doing OAuth2 stuff. It took a couple days
           | to read through [Google's] ten-thousand lines of code, so
           | then I went and looked for other libraries. There's `python-
           | oauth2`... it's the second version of python-oauth, it
           | doesn't actually do OAuth2. But that took a while to figure
           | out. So that one was a little bit better, 540 source lines of
           | code, 15 classes, but I wasn't going to put that in either
           | because it didn't actually do what I needed to do. So I
           | rewrote that to just do bearer-token authentication, it's
           | 'python-foauth,' or if you prefer, 'eff oauth.'"
           | 
           | -- Jack Diederich, "Stop Writing Classes",
           | https://youtube.com/watch?v=o9pEzgHorH0
        
             | neolog wrote:
             | In cases where the name is ambiguous you can use another
             | name like python-oauth-v2.
        
               | 0xbadcafebee wrote:
               | With CPAN this was solved by hierarchical package/class
               | naming.                 Net.pm       Net/IMAP.pm
               | Net/IMAP/SSL.pm
               | 
               | ^ Each of those is published by a different author, and
               | inherits the previous one to add features. As a result
               | CPAN is a tremendously useful library of OO, not because
               | they're all different, but because they are designed to
               | inherit and extend existing code, rather than re-write
               | the whole thing and have 500 differently-named-almost-
               | identical codebases.
               | 
               | CPAN's been around for decades, and everybody talks about
               | DRY code, and yet no other language seems to want to
               | actually reuse and extend code.
        
           | one_off_comment wrote:
           | What's the difference? It's not like the old version of the
           | library ceases to exist. What's the difference between jinja
           | 2.0 and jinja2 1.0?
        
             | wccrawford wrote:
             | IMO, the difference between those 2 should be that jinja2
             | 1.0 should be a complete rewrite, possibly in a different
             | language, and probably even a mental shift in working with
             | it.
        
             | badsectoracula wrote:
             | Someone who cares about not breaking others' code can keep
             | working on the existing project by fixing bugs, adding new
             | features and even make a "2.0" version that remains
             | backwards compatible.
        
             | [deleted]
        
             | neolog wrote:
             | The difference is whether you break old code for users.
        
               | Stampo00 wrote:
               | Both would break old code for users. If you don't want to
               | update your code don't update your dependency.
        
               | neolog wrote:
               | No, installing jinja2 doesn't break my jinja-using code.
               | Installing 2.0 does.
        
               | one_off_comment wrote:
               | That sounds like a package manager/module system issue,
               | not a library issue. A sound system would let you use
               | both as long as you weren't ambiguous with your imports.
        
             | simonw wrote:
             | The difference is tooling. Tools like Dependabot know that
             | Jinja 2.0 is a major release of Jinja. They have no way of
             | knowing that a package with a separate name is related to
             | the first one.
        
               | neolog wrote:
               | The problem is that the two incompatible packages are
               | only weakly "related": they're just two packages in the
               | same space that may share some authors.
               | 
               | What if I want to use code from both packages?
        
               | simonw wrote:
               | Yeah that's a reason in most languages to go with the
               | separate package names.
               | 
               | As a maintainer I'd much rather not have to put in that
               | extra work just for the tiny minority of my users who
               | might someday want to run two versions of my library in
               | the same project.
        
             | nonameiguess wrote:
             | The practical upshot is:
             | 
             | 1) Many Python applications are not pinning dependencies,
             | and even if you are personally, if jinja is a transitive
             | dependency you might pull in a breaking change. You can't
             | if the new package has a different name.
             | 
             | 2) You can more easily simultaneously use both to gradually
             | transition your code to use the new API. I don't believe
             | Python package managers have any built-in way to use an
             | "all" conflict manager like Apache Ivy, so you need a
             | different name to enable this.
        
               | Zababa wrote:
               | That sounds like limitations of Python rather than an
               | universal thing.
        
           | shadowgovt wrote:
           | In one sense, you could. That's just taking the semantically
           | significant information and moving it from the major revision
           | number to the name.
           | 
           | But then most systems are going to consider those libraries
           | to be entirely separate, most search engines are going to
           | make it hard to find out about one if you find out about the
           | other, and so on and so forth. Major version number also
           | implies that if you have no reason to choose one over the
           | other, you should be choosing the most recent one.
        
           | ajmurmann wrote:
           | Any reasonable dependency management tool should allow you to
           | pin down any part of the semver version. For example on
           | regular upgrade only pull patches or minors and require a
           | manual change to upgrade otherwise. Appending a version
           | number to the library name is a heck around completely
           | inadequate dependency management tools. A language not having
           | a tool en par with bundler, cargo or yarn is a massive
           | negative for me when looking at new languages.
        
         | madeofpalk wrote:
         | > without ever breaking backwards compatibility.
         | 
         | Without ever _intentionally_ breaking backwards compatibility.
        
           | OJFord wrote:
           | Or rather 'knowingly'. If you didn't intend it, but you find
           | out (e.g. user reports it), you should still bump major. If
           | you consider yourself to actually be 'doing semver' that is.
           | And even yank the minor breaking release I suppose.
        
       | [deleted]
        
       | 0des wrote:
       | I disagree with the author. However, I don't think this was meant
       | to be taken literally, but more as a tongue in cheek observation
       | of the poster's perception of their own situation.
       | 
       | As an aside, recently, I've started doing YYYY-MM-DD for
       | releases. I don't know why, but that's how I ended up
       | subconsciously, after using semver for years. Currently, I
       | version the API, and date the release. I have not yet had the
       | audacity to pull this off in any larger projects, but small
       | tools, internal releases, who's going to judge for trying
       | something new where the risk is low?
       | 
       | I'm not saying it's right, just that it works for me.
        
       | willm wrote:
       | Tweet author here. Please don't @ me. I was only half serious.
       | 
       | The context was re Python libraries. I increase the major version
       | when I revise the API, even if it's single method. To my mind,
       | that is a failure on my part to come up with the perfect API on
       | the first pass. Of course it's going to happen and I don't lose
       | sleep over it.
       | 
       | I'm not dissing any project that doesn't start with a 1.!
        
         | kirse wrote:
         | If an API is like a painting, then a changing landscape could
         | be one reason you can paint it accurately each time but still
         | need to make later revisions. "All models are wrong but some
         | are useful" applies here as well. Most of SW iteration is about
         | adjusting the painting/model to match present realities.
         | 
         | Either way the tweet cracks me up because it's just a matter of
         | perspective that is giving some folks a good rankle.
        
         | j1elo wrote:
         | People are just reacting strongly to a word that I guess in
         | their culture has too many negative connotations. Your idea was
         | pretty much on point and made for a fun tweet, and I think it's
         | good enough without needing to split hairs between the slightly
         | different possible interpretations of the word, as some are
         | doing.
        
       ___________________________________________________________________
       (page generated 2021-08-06 23:02 UTC)