[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)