This is a great move and hopefully inspires people to take a different look at what versioning is. Right now it serves two masters: marketing and engineering. If everyone just used semver as almost build numbers with meaning, and completely put aside the 'hidden meanings' of 1.x.y or 2.z.w, we'd be in a much better place.
The main issue with getting hung up on "what is a 1.0" or "when is this 2.0?" is that even if you finally make sense of it for YOURSELF, everyone outside has such a different interpretation that its meaningless no matter what. However, semver for engineering changes has meaning no matter what. Why hurt your users by introducing a breaking API change in the minor category just because "it doesn't feel like a major change"?
I wish we could just rename version to build, have it be semver and be done with it. Then version can be whatever you want and is completely ignored by computers and engineers. Call it version 1.0, version dog, version whatever "feels" right, while we start moving to a world where we can start maker safer decisions.
The problem with creating two values is that it becomes harder to communicate if you are talking about version x or build x.
I wish semver simply moved all digits up one place. The second digit can then mean 'api break', whereas we can easily use the first for marketing purposes.
I loathe this about Android and OS X. I know that Marshmallow is thr latest and greatest but when I check my phone tells me that it's on 5.0.2. I have no idea what to do with that number. I need to Google the version to see I'm still on Lollipop.
Is that really a 'horrible' experience? Once you've googled 5.x and you know it's Lollipop, do you not memorize that? I mean how often do you check your phone for what version of the OS it's running?
It would be fine if Android bumped major version numbers. But if I have to think about versioning once a month then it's hard to remember whether it was 5.1 or 5.2 or 5.3.
I feel the same about Ubuntu, it's confusing that the download page and /etc/issue refer to 15.10, but when searching for packages you need to know that's Willy:
The fundamental problem with Semver is that the jump from a 0.x.x series to a 1.0.0 is incredibly difficult to call, and often gets delayed almost indefinitely.
0.9.9 -> 1.0.0 means the opposite of 1.9.9 -> 2.0.0 - the former is an observation of stability ("things are so stable we can leave the 0.x.x series"), the latter is an active statement of a breaking change ("we can't honour the 1.x.x API any longer"). Lots of projects miss the window somewhere around the 0.3.0-0.7.0 versions.
We badly need a Semver', which is identical to Semver but starts from 1.0.0 and removes the 0.x.x rule. React is basically retro-fitting Semver' into their project.
I think there's absolutely nothing wrong with what React did just now -- they have used the system effectively. (The only problem is that they waited this long to do it).
They realized React is _already_ used in production, so it should _already_ be 1.0, and they should be using semver so consumers know when there are breaking changes between versions and when there aren't.
They did exactly the right thing.
The semver doc already says:
> If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.
But it is true that this is frequently ignored by people who otherwise think they're doing semver.
I guess _one_ way to deal with that would be to remove "0.x" from semver altogether -- the first version you are allowed to release is 1.0, and it must follow semver rules.
But there are plenty of people who don't use semver at all, that would just increase if you removed the availability of pre-1.0 unstable releases.
I wish everyone used semver, and I wish everyone who said they were using it actually were using it, and I wish everyone using it followed that part about "If it's being used by tons of people in production and/or you are thinking about backwards compat at all, it should already be 1.0" But what can you do.
The semver spec is good already -- I don't agree there's a "fundamental problem" with it in the area you speak of, the problem is people not caring about semver. Changing what's written in the spec won't improve people's behavior in these areas, alas.
For stuff I write, as soon as _I_ am using it in production, it's 1.0. That's pretty straightforward and objective. Sometimes I give it a couple weeks in production myself as a beta/rc before I tag it 1.0, to take the pain of early bugs myself instead of foisting it on others. No more than that.
It's not always that simple, and it may not be totally objective down to the timestamp, but we can think of _many_ cases where people kept an 0.x version number _long_ after it was obvious they shoudln't be -- the authors were using it in production, they knew hundreds or thousands of developers were using it in production, they knew they _were_ thinking of backwards compatibility.
React was my prime example before now.
The problem isn't different judgements on grey areas, the problem is people completely ignoring the intent of the 0.x versioning -- so they can maybe sort of pretend they are doing semver, while not doing it at all.
The first time you realize you can't make an enormous backwards compatible change without telling anyone, or you're a jerk -- is another good milestone.
Who cares if sometimes it could have been somewhat earlier or later. I'm pretty sure if everyone actually tried, it'd work out orders of magnitude better.
If 0.x versions just "weren't allowed", it doesn't _reduce_ the temptation people have _not_ to do semver. 0.x is just a big advertisement "We're NOT using semver... yet, but plan to later. And also this software is super unstable and you really ought not to use it in production" And should be understood thusly.
The problem is when people keep using 0.x, but are clearly _not_ sending that signal. Those people should be shamed.
Well, it's not as if "1.0.0" is meant to offer any logical and universal guarantees for code quality, completeness, etc. compared to, say, 0.7.x -- apart from what semver asks for.
So, as long as it is relatively stable when bumped to 1.0.0, and later releases follow to major/minor rules of semver, it doesn't matter much.
For all of our internal projects we don't push to production til 1.0.0- but because people have different opinions and we live in the world at large we don't have a hard rule of using someone else's code < 1.0.0. We'd just be missing out on too many useful projects.
If it the major version changes for us, the API has probably changed. If it's a minor version bump, the API has DEFINITELY not changed. Rev changes are your typical bug security/performance fixes that are limited in scope.
Who decides all this? If there's any question, just pick the more important signal of the two.
The answer doesn't match the question. The question is, "How do I know when to release 1.0.0?", whereas the answered question seems to me more, "How do I know if I already should have released 1.0.0?"
It's a statement about hindsight, not planning. IE, if I'm wondering if can I make a 1.0.0 release even if I think the project won't have users until, 1.4.x but 1.0.0 represents a logical core, that scenario is not addressed by the "should probably already be 1.0.0" after the fact tests provided.
It's about what to do with your code as it is right now -- at every now.
>IE, if I'm wondering if can I make a 1.0.0 release even if I think the project won't have users until, 1.4.x but 1.0.0 represents a logical core, that scenario is not addressed by the "should probably already be 1.0.0" after the fact tests provided.
I don't think project authors should be worried about making an 1.0.0 in advance, that is, before they have written the code and releases several versions. At which point it comes down to the "hindsight" answer as a heuristic.
E.g. "if I'm wondering if can I make a 1.0.0 release even if I think the project won't have users until, 1.4.x" -- there's just no way to knowing whether the project will "have users" until it has.
Why is your dev/qa/prod code different? For that matter, you could use a julian date... break.year.julian if, for some reason more than one a day break.year.julian-patch##
Dev is frequently the next breaking change and/or code tested solely by is creator.
QA is code going through the in-house QA process and is basically a previously nightly build which is trusted enough to be tested against live data.
Prod is the last QA promoted to production + any hotfixes.
Library changes are slow due to the need to verify we aren't breaking production systems so we frequently have a Prod that doesn't match QA that doesn't match Dev because the process can take a month for breaking changes.
Even for non-breaking changes, we generally freeze production for ~1 week if the changes are substantial enough that we might have missed something.
We can't exactly ignore production bugs for 1-4 weeks.
---
The problem with Julian Dates isn't they aren't immediately human readable which is useful for lining up what was running when.
0.x.x makes sense if you explicitly keep a "the ABI is fluid and will break at any time" rule while using it. It basically means that no downstream project can consume a 0.x.x release—which makes sense. 0.x.x is an exploratory phase, and should be passed through as quickly as possible. 1.x.x is then the first "ABI contract": the point at which you can make a call to the project as a library, and know that that call's semantics won't change or break throughout the 1.x.x series.
(You could determine something like this mechanically pretty easily... if your platform had anything like "ABI specification files", the way many platforms have "dependency specification files." 1.0.0 would then be the first time you generated an ABI "lock file", that would then be used by your toolchain to fail builds that violate it across the 1.x.x series. To delete-and-regenerate the ABI lockfile would be to bump the major version.)
The real problem, though, is that many projects are too big to have a single version sum them up. People need to break components down along stability boundaries—places where rate-of-change changes—and then give versions to those components. NPM libraries are a sort-of-good example of this, though I think there might be better.
This kind of made sense with React as even with this release they were struggling to decide if `context` should be public at all, what shape a "renderable" component should have, etc. Since they've finally decided on these issues with this release, they wouldn't have been able to release it as another v0.x with a straight face.
> We badly need a Semver', which is identical to Semver but starts from 1.0.0 and removes the 0.x.x rule. React is basically retro-fitting Semver' into their project.
Wouldn't that discourage releasing experimental code? I think the very first public release of react was 1.0.0 and they incremented the major version for subsequent incompatible changes, the current major version would be ridiculously high. I know if I did this for experimental code I throw up on github, this would be true.
> Experimental code doesn't have to go to a package manager.
Just because code is experimental doesn't mean it doesn't need to go in a package manager or, more to the point, doesn't mean it won't benefit from having version numbers.
> We badly need a Semver', which is identical to Semver but starts from 1.0.0 and removes the 0.x.x rule. React is basically retro-fitting Semver' into their project.
I can see the desire for this from a code consumer's perspective, I'll argue that this is mostly impossible. New projects often start because there's a new problem (a software architecture, a set of algorithmic tools, etc.) with an inherent learning curve. The 0.x releases reflect the inherent instability of this real-world learning process. Switching to your proposed Semver' model implies that projects must use the compatibility modes (e.g. deprecate-before-removal as this post describes React adopting) of more mature software before their ideas are even partially baked. Many 0.x-era updates (e.g. x++) are near-complete rewrites of the API or sometimes even the entire nascent codebase. I'll hypothesize that a major contributing factor to successful projects gaining wide adoption is the ability go through that vital period of rapid churn.
There's nothing you can do in a 0.x.x release that wouldn't also conform to the Semver rule around incrementing the MAJOR version: http://semver.org/#spec-item-8
The idea of 0.x.x reflecting a level of instability not reflected by MAJOR version bumps is cute in theory but broken in practice.
>The fundamental problem with Semver is that the jump from a 0.x.x series to a 1.0.0 is incredibly difficult to call, and often gets delayed almost indefinitely.
That's not a problem with semver. That's a problem with these projects not being stable and being continually changing.
If after a period of rapid development a project has been stable, and with no major bugs for months, with only minor changes, they can just as well jump to 1.0.0.
15 sets the right impression. Because it's high, it implies that it's changed 14 times already, and will probably do so again in the future.
I've been burned badly before by breaking API changes in patch releases. (Rails 2.4.5). If you're not afraid of bumping the major number on even a minor API change, then it makes it more likely that you will actually do so rather than paying lip service to the idea of semver.
Gives the opposite impression to me. If I see a component using semver at version 15.x I'd assume it's very unstable (unless it's very old).
So, contrary to what spicyj is saying, to me it seems to create the most confusion in the long run at the expense of addressing some short-term concerns ("people already call it React 14"). I'd much prefer they switched to 1.0.
You might want to take a look at the blog documenting the releases[1]. Breaking changes happen, but not more often than once in three months. Every breaking change is preceded by a deprecation warning in the previous release, and many changes are automated through codemods. And of course the API surface area is small which is why it’s possible to move fast without breaking things.
Don’t forget Facebook has a large React codebase so it cares very much about automating migrations.
If React switched to 1.0, with some breaking changes every three months, it would be 14.0 again in a couple of years. Then googling for tutorials would get confusing. Why not do that now?
I would not describe a breaking change every three months as stable.
I like the upgrade paths but can you really say with a straight face that an API is stable if the code you write could be invalid a few months later? That's a maintenance nightmare!
Are you using React? I’m curious if this is your feedback on the pace of changes, or if this is just a guess.
In reality React API surface area is pretty small so most changes are automated by codemods. Codemods are programs that modify your source code. They work pretty well because Facebook uses them on a large scale.
Not everything is covered by codemods but generally the feeling I get from talking to the community is that React moves at an acceptable rate, and changes take about a day to apply once a three months for most apps. Deprecation warnings also give you several months to fix use cases that will be unsupported in the next version.
In return, this allows React to become a better library and not stagnate. I see your point in theory but please talk to the people using React, and you might find that it is not a problem in practice.
> Breaking changes happen, but not more often than once in three months.
Once every 3 months is too frequent. Imagine curl broke compatibility every 3 months and you had to relearn curl. How terrible! I'm pretty sure you'd use something else after a while.
I'm not saying React should be as stable as curl, but it should be striving to become that. The JavaScript community loves to have these eternally evolving libraries that are never actually stable and that's not good for anyone. You should have a long term plan that says "we still don't know what this library should be, but within 2 years we should have it figured out". In reality it feels like JS libs only become stable after they've been abandoned.
Are you using React and voicing your concern? Or are you making a guess?
Every three months might be too often for a tool like curl. In case of React, the community seems to be happy with the tradeoff between moving forward and keeping the old code working.
You might want to ask a few people who use React to draw the conclusions. I talk to a lot of people in the React ecosystem, and so far the feedback I heard is that updating React has been the least of their worries, compared to some other libraries in the ecosystem which are far less stable.
Personally, I updated a fairly large (~1000 modules) app from React 0.11, to 0.12, to 0.13. After the ecosystem catches up and libraries release compatible updates (if they need to), it always took less than a day to upgrade. Doesn’t seem like a big price to pay for avoiding stagnation and actually improving the library.
And I wasn’t even using codemods which React team ships (and widely uses internally at Facebook). Codemods just convert your code through most of the API changes automatically.
> Every three months might be too often for a tool like curl.
Why should a tool for creating dynamic HTML be held to a lesser standard? I wouldn't expect the level of stability that curl has yet, but I would expect it to be an eventual goal of the project. The reason why we build abstractions is so we can eventually stop worrying about a problem; that can't happen without stability.
> You might want to ask a few people who use React to draw the conclusions. I talk to a lot of people in the React ecosystem, and so far the feedback I heard is that updating React has been the least of their worries, compared to some other libraries in the ecosystem which are far less stable.
That's because you talk to other enthusiasts who are happy about changes. Try asking people outside of the React Slack channel for a wider perspective.
I've had people complain on my projects about upgrading apps using APIs deprecated 2 or 3 years prior. And I feel genuinely bad about it, because if they are having to justify spending 3 or 4 days refactoring their app (which is hard to do in a lot of companies) because I made an API mistake 3 years ago... I feel bad about it. We should strive for better stability.
Thank you for your feedback. Would you please name specific API changes in React that were problematic and forced you to spend more than a day migrating? This would help me better understand the issues.
But HTML/Javscript is a moving target in itself. HTTP moves slower. So an HTML library is by it's nature going to have to move faster than an HTTP library.
You also have the ability you like, you know, not upgrade. Of course you might miss out on some of the newer and fancy features that come with the upgrades, but you still always have control.
If React 15 was good enough for you when you started using it, it doesn't necessarily fundamentally stop working when React 16 ships.
>If React 15 was good enough for you when you started using it, it doesn't necessarily fundamentally stop working when React 16 ships.
No, but your project is seldom 100% finished either. So as you do minor changes to it, and want to use some new lib, you find out that it's not compatible with your old version.
And libraries stop get maintained too -- and when you finally try to make the conversion it will be harder the longer you have waited, because aside from porting your code to all new React stuff, you'll also need to find replacement for all those libs at once (not piecemeal, which would be the case if you kept the project up to date faster).
This could also happen for all kinds of external reasons too -- e.g. you use a third party service and they change their API. Or you update your OS and your old libs suddenly stops working. Or a browser deprecates some feature (like Object.observe that Google warns that it will be removed on March).
The biggest issue in upgrading is that all these libraries tend to change their APIs in totally negligible but backwards incompatible ways frequently. Subpar documentation for upgrade paths is plentiful.
I wish many of these libs could stick to an api instead of needing every piece of new Javascript hotness every version. =/
I am not sure this is the case with React. If you look through the blog with releases[1], you will find that breaking changes happen not more often than once in three months, that every breaking change is preceded by a deprecation warning in the previous release, and that many changes are automated through codemods.
Facebook has a large and growing React codebase, and they use master version of React. Therefore making migrations easy is in its best interests.
It's more the case for other packages in the ecosystem (especially when combined together) which is part of what this react change aims to help, I realize. E.g. react-router is something I've had trouble with over time, as one example. Getting hot loading set up also gets trickier with each new project (which I'm sure you have experience with ;) Getting react transform running a month ago between all the version incompatibilities was pretty tricky. Following a chain of deprecated projects is not super easy generally.
I see what you mean but this has no relation to the React release policy. React itself moves with a pace that should be easy to follow.
Community projects like React Router move faster but this is not something the React team can help you with. If you don’t want to keep up with the breaking changes there, you can wait for the project to stabilize. For example, you can use Backbone Router which hasn’t changed for years.
Finally, if you use something as experimental as hot reloading, please expect it to be tricky to set up until it’s part of official React. This is very experimental territory and there is so much work involved in just making it work that making it stable and easy is not a priority yet.
Folks have been using React in production since way before version 0.12, which is when Facebook should have released version 1.0. Releasing 1.0 doesn't in any way limit your ability to make changes in the future. It does, however, allow for more nuanced semantic versioning with the full range of major, minor, and patch versions. This extremely is useful for both library authors and consumers.
Better late than never, I suppose, but I just don't understand the pointless sentiment that results in waiting to release a fabled "1.0" release.
Everytime I read something about SemVer, breaking changes, etc, I can't help but think about how well Symfony (the PHP framework) handles this.
With Symfony, major version changes are not there to break things or bring in tons of new stuff. Instead, it just removes BC layers for stuff that has previously been working but deprecated (with appropriate deprecation warnings).
This makes it easy to switch to a new major version: simply fix all deprecated calls and upgrade, done. At least that's what I experienced moving a project from Symfony 2.x to Symfony 3.x.
It sounds like this is exactly what Facebook plans on doing?
> Therefore, we're committed to making it easy for most components and libraries built on top of React to be compatible with two major versions at the same time. We will do this by introducing new APIs before completely removing the old ones, thereby avoiding those cliffs.
As long as they provide deprecation warnings for APIs that will be removed in the next version, it'll work exactly like you say.
And, to be clear, this is what React team has been doing all along. When you fixed all deprecation warnings in 0.12, you could update to 0.13. React just moved “0” at the end because it has been used in production for years.
I see many comments on the pros and cons of various version numbering schemes, and I recall many similar discussions going back decades.
I have no idea why it has never occurred to me to ask the following question [1]: how is version numbering done in disciplines other than software?
Software is young compared to most engineering disciplines. Surely this problem was solved long ago in non-software disciplines and their solutions have been tested by decades, or in some fields even centuries, of practice.
Use ISO 8601, and add whatever flags you need, and establish some minimum standard vocabulary the AI can search for. :>
Development #D:
"2016-02-16T15:17:32+00#D#API"
Release #R:
"2016-02-19T17:37:21+00#R#API"
Now anything can look for dates to figure out the age of whatever it is that's running on the system, and maybe even warn about it, disable it, exploit it, etc.
(AmigaOS encouraged a $VER: prefix you could scan for, IIRC.)
If you still want a custom numbering scheme, just append it to the version string somewhere:
#API could mean there was a change to the API. Review your dependencies.
#+API could mean a function was added, but the existing API is stable. (Unless #API was also added separately, in which case a review of the change log is needed.)
#-API could mean a function was removed. Review your dependencies.
From look at your examples, I'd say what's wrong is that they are very difficult to read.
At a very brief glance I didn't notice the change between 16 and 19, and my eyes were drawn to the time, which let's face it, is probably next to useless.
And it also doesn't have any of the benefits of semver, like signaling breaking changes.
I'm not sure how to address your first concern (readability), because I don't have the context in which you would need to distinguish one version from another; as opposed to something presenting the versions to you, like a program, website, listing somewhere.
The format should be programmatically scanned for, and extracted, and represented in various ways; days ago, hours ago, minutes ago; sorted by newest, oldest; grouped by last three months, etc.
> And it also doesn't have any of the benefits of semver, like signaling breaking changes.
That's the function of tags. Agree on using #Fix for a corrective release, #Feature for a feature release, and whatever else makes sense. Ideally, there would be a minimum, standard vocabulary that makes sense.
That requires looking at every version in-between to know if a version contains breaking changes from the version I'm coming from. With semver I know that if I'm on 13.x and the latest release is 15.x, that there are potentially breaking changes. I also know that if I'm on 13.1, then 13.6 should be compatible. With your scheme, I would have to inspect the 5 versions in between to see what they were tagged with.
(I'm prefixing it with Semver because it's defined.)
This scheme is mainly about making the date and time an intergral part of a versioning format, which in turn makes it easy for machines to figure out the age of components, and automate checks.
Perhaps tags could then help add more information.
So just search for "$Version:" across multiple platforms; text files/scripts, videos, pictures, executables, etc.
Problems: Text encoding. A search may have to cover all variants. UTF-LE, UTF-BE, UTF-8, etc, but if written in isolation, it should be UTF-8.
There could be established standards for where to store such information, to optimize lookup for specific data formats.
The +00 is to emphasize UTC time (which all of these datestamps are stored as).
I suspect some people find it too verbose to use dates, but that's irrelevant; this is the minimum amount of information required for a more general versioning scheme, in my opinion.
In the course of this thread you've proposed at least six slightly different variations of the concept - what do you think are the chances of getting everyone to agree to just one of them?
The reasoning for the strategy is sound, but does anyone know the rough cost of leaving in the deprecated apis from the previous version, in terms of additional gzipped file size percentage? Say from 13 to 14 as an example?
Further to that, anyone know how effective various dead code elimination tools are at stripping out those unused deprecated apis, for bundled apps that don't have any dependencies requiring anything less than the latest react version?
I don't know why they didn't just take this opportunity to call it version 1. It seems like the right time. The React Router folks just went through this, with a significant struggle in moving quickly from version 1 to version 2. But it turned out OK.
It seems like there's a fear in making the call. Version 1 should be celebrated.
I don’t get the _fear_ of releasing the 1st version of a library at `1.0.0` and then doing major bumps whenever needed. That’s why semver exists in the 1st place.
There seems to be a lot of FUD around this subject.
So they're going the Google Chrome route, already at v14. Doesn't really matter of course, but it's off-putting. I would have preferred them to use 1.0, clearly indicating it's production ready.
No, this has nothing to do with Google's rapid release cycle or versioning scheme. As stated in the article, the API is stable so, it makes sense to switch to a semver scheme.[1] From an engineering perspective, this is a system that makes perfect sense for all libraries to adopt.
They choice 15 as the starting MAJOR version because people already referred to 0.14.x as "React 14", avoiding any possible naming confusion. They will remain at 15 as long as there are no major features or API breaking changes introduced.
> Our business as well as many of yours all depend heavily on the use of React as a core piece of our infrastructure. We're committed to the stability as well as the progress of React going forward.
Yeah, it doesn't sound too stable to me either. </sarcasm>
Right, but they should not be indicating it's ready for production right now...simply because it's been production ready for ~2 years, stable for longer really.
We have had React in production for almost 2 years...it has been extremely stable.
It should be clear that React is very mature, I think 15.0.0 fits.
I am really looking forward to the day we get an industry-wide standardized versioning system. I don't care whether it's semver or not, I don't care if it's 98% perfect and 2% pure evil. I don't care. I just really want to see a universal versioning system. Unfortunately though, I don't think that day will ever come. At least not in my lifetime.
> the day we get an industry-wide standardized versioning system
Never. A hobby project nobody touches, an internal project at a Fortune 10 company, a huge open source project like WordPress, and a moderately successful SaaS app do not need to have identical versioning systems behind them.
And depends on the environment and project... if it's a website, then the core release would best be platformNum.releaseNum ... where platform is the underlying platform/architecture, or full rewrite number... Where release number is just incremental... and maybe tying to a git hash or something beyond that.
The main issue with getting hung up on "what is a 1.0" or "when is this 2.0?" is that even if you finally make sense of it for YOURSELF, everyone outside has such a different interpretation that its meaningless no matter what. However, semver for engineering changes has meaning no matter what. Why hurt your users by introducing a breaking API change in the minor category just because "it doesn't feel like a major change"?
I wish we could just rename version to build, have it be semver and be done with it. Then version can be whatever you want and is completely ignored by computers and engineers. Call it version 1.0, version dog, version whatever "feels" right, while we start moving to a world where we can start maker safer decisions.