Backbone: Follow SemVer

Created on 22 Nov 2013  ·  27Comments  ·  Source: jashkenas/backbone

Backbone.JS is a project with a large following, but regular "minor versions" (e.g 1.1.0) break compatibility with existing Backbone codebases.

To make it easier for developers to determine if a new version of Backbone includes backwards-compatible features vs backwards-incompatible api changes, Backbone's versioning scheme should follow semantic versioning (SemVer)

The gist of semver is as follows:

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.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

This would make the existing version (1.1.0) a 2.0.0 version (as most of the changes broke existing API) which would clearly indicate to developers that the API is different, and allow developers to utilise npm's wildcard versions (e.g "1.x", "~1")

change wontfix

Most helpful comment

What's the problem with being at Backbone 43.0.0?

  • Sent from Chrome 32.0.1700

All 27 comments

Thanks, but strictly following "semantic" versioning wouldn't work out very well for Backbone. Given that the project is almost all surface area, and very little internals, almost any given change (patch, pull request) to Backbone breaks backwards-compatibility in some small way ... even if only for the folks relying on previously undefined behavior.

If we strictly followed "semantic" versioning, it would probably be Backbone.js 43.0.0 by now — which doesn't help anyone evaluate the actual progress of the project.

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

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

MAJOR version when you make a major new release, or significantly update and/or stabilize the API.
MINOR version when you add minor new features.
PATCH version when you make tiny changes, likely to go unnoticed by most.

This allows folks, immediately upon hearing about a new release, to get a rough sense of its scope. As to backwards compatibility — ideally _every_ release, even major ones, are backwards-compatible. And when they can't be, because an API is changing, it should be done in a way that isn't too difficult to upgrade.

But avoiding any change to the API, and waiting for a "MAJOR" release to be ready would be a terrific impediment to progress. And the alternative of frequently incrementing the MAJOR version number is incredibly unhelpful.

Honestly, I'd prefer a simpler scheme that just used BIG.SMALL version numbers — like most desktop applications do ... but I'd worry about it breaking package managers and other tooling.

What's the problem with being at Backbone 43.0.0?

  • Sent from Chrome 32.0.1700

+1 for spadgos@ question. Version numbers are arbitrary. For some reason, we have agile web apps trying to keep within the same ranges as OSes. Many apps freak out about going past 10...but most of the projects you're modeling off of (Windows, Linux, etc) have 1 year/multi-year dev cycles before release, so 1.x -> 2.x is a big deal. An agile project moves very quickly, incrementing quickly makes sense too.

I also disagree with the reasoning behind this.

Marionette is on v1.2.3 right now, and is doing it's best to follow strict semantic versioning. So far, we haven't had any issues even though we are "all surface area" as well. We've added new features. We've fixed bugs. But v1.0 is still compatible with v1.2.3. We've deferred tickets for a v2 release when they are API or expected behavior breaking changes.

Major releases with breaking changes don't have to happen every week when a pull request is accepted. These can (and should) be pooled in to major release that encompass enough value for a large release with a major version bump.

As it stands, breaking compatibility in a v1.1 release causes a lot of pain for plugin and add-on developers, like the MarionetteJS team. We had to back-fill behaviors with patches in our code, so that we can remain viable for both v1.0 and v1.1... it's not a fun situation. The ripple effects of a core library like Backbone having breaking changes, are enormous... it's not just Backbone that is affected.

I agree this seems more like a case of "don't want to" rather than "can't." Breaking changes such as https://github.com/jashkenas/backbone/pull/2461 have no real sense of urgency, and could have waited for a major version update if you don't want the 43.0.1 problem.

For me, the biggest problem with Backbone not respecting semver (among other things) is in teaching and evangelizing Backbone. It's not great to tell a group of students or potential customers that everything in your stack is going to work in a certain way... except for Backbone.

There have always been two huge caveats when "evangelizing" Backbone: it's not AMD out of the box, and it doesn't respect SemVer, so don't take the version numbers seriously. One of those is fixed. Let's fix the other.

Honestly, I'd prefer a simpler scheme that just used BIG.SMALL version numbers — like most desktop applications do ... but I'd worry about it breaking package managers and other tooling.

@jashkenas we could just always leave the 3rd digit at .0 :)

That'd probably map semantically to SemVer a little closer than what we're doing right now. Maybe that'd tamp down on some of the passive-aggressive crypto-political sniping about how it's somehow technically wrong not to follow SemVer.

I think Bob's point is right in that it's more important to clearly articulate what system we follow, irrespective of what system we follow.

p.s. I did not mean to imply that @keithamus's issue is passive aggressive and I'm sorry if it came off that way. Definitely legit to discuss how Backbone communicates changes to users.

:+1: for semver. I am primarily interested the version of a given piece of software not as an index of its progress but of its compatibility.

Generally, after 1.0 (when I'd expect things to be mostly stable and working), version numbers are largely meaningless as indicators of progress. Software X at version 10 may be much less mature, have fewer features than Software Y at version 2. If you want to know about the progress of a piece of software, you have to look at its changelog or roadmap.

Knowing that Backbone (or whatever) is at 2.4.3 means nothing in terms of its features. It _should_, however, mean that I can upgrade from my 2.0.4 without anything breaking.

If we strictly followed "semantic" versioning, it would probably be Backbone.js 43.0.0 by now — which doesn't help anyone evaluate the actual progress of the project.

A very minor / maybe nonexistent problem. Not following semver? Big problem.

:+1:, semver is a must-have for such a big project.

I'm with @knowtheory. 43.0.0 looks a bit odd but I think 1.43.0 would be fine and no one would get surprise breakage after npm install.

Who cares about version numbers being high?
It's a standard, if you can use it, you should use it.
I don't even understand why this discussion is going for so long.

:+1: It would have prevented some of the issues in #2996 and #2997, and problems others have had w/ several other Backbone releases.

@braddunbar that (and the rest of the reasons "against") sounds like it's valuing the aesthetics of the version number over its actual meaning.

Thanks, but strictly following "semantic" versioning wouldn't work out very well for Backbone.

I think it's more about Backbone working well for its users (with dependency management). Which following semver would guarantee…

More frequent releases would help catch showstopper bugs faster. I think it's too much to ask people to constantly run edge versions of Backbone just to get the bugfixes they need.

For packages in npm or bower, this isn't even up for debate.

When you publish a package with npm or bower, semver is part of the API contract you enter into. When you break that contract, you break other modules that depend on yours. You break production code that depends on your module.

The question is not, "should we use semver?" The question is, "do we want to be good citizens in the ecosystem?"

If the answer is no, that should be advertised loudly and clearly, because it's not safe to just install your package like you would any other package that follows the API contract.

When you publish a package with npm or bower, semver is part of the API contract you enter into.

No, it's not. npm install --save [email protected] is not an onerous requirement.

@akre54 I am interested in your perspective about semver I know @jashkenas thoughts on it but what are yours.

@akre54 Yes, it is. npm assumes that all packages in the repository follow semver. That's how it determines which packages are compatible with which.

From the package.json doc:

"Version must be parseable by node-semver, which is bundled with npm as a dependency. (npm install semver to use it yourself.)"

If your version numbers _lie_ when they're interpreted as semver, that's not a correct parsing. Thus, you're breaking the package.json contract, and you're breaking compatibility with how people use package versions in the npm ecosystem.

That's not just a matter of personal preference. It's a matter of package interoperability.

Is it possible to force your package to play nice if it doesn't use semver? _Sure_, it is, but if you don't call it out loudly and boldly at the top of your readme -- few users will know that it's necessary, and when you introduce a breaking change, their code could very easily break.

Once you publish your packages to package repositories, versioning becomes part of the interoperability contract. You ignore that contract at the peril of your users.

npm install --save [email protected] is not an onerous requirement.

Knowing which of the thousands of packages that go into a full blown application you have to do this with _is_ an onerous requirement. Forcing users to tightly lock down the versions of all their packages because a handful of modules don't follow the rules _is_ an onerous requirement, because it complicates the matter of keeping up with bug fixes, security patches, etc...

There are very good reasons to follow semver. "My package number might get really big" is a terrible reason _not_ to use semver. Tracking the progress of your application is a distant second reason for package versions. The most important function of the version is to know, "will this version work with my application?"

BTW, if your package number would get really big, maybe that's a code smell. You only have to bump the major version when you make a _breaking change_. A breaking change by definition is one that _breaks the open/closed principle_. Open for extension, closed for breaking changes. All good APIs follow the open/closed principle as closely as they reasonably can, so that users can keep pace with the API, and changes don't break existing code.

I think the lesson learned here is "don't use ~ or ^ when pulling in Backbone via package.json"

@akre54 I am interested in your perspective about semver

In general I agree with the arguments here, but I do have to wonder if bumping the major version is the best course of action on _every_ breaking change (and again, with Underscore being mostly surface area, that's _a lot_). Underscore is used in a great deal of third-party libraries, and requiring them all to keep up with huge versions would be onerous and perilous. (Should a package released today depend on Underscore up to version 2? 1.7? 1.6.x? Should it pin its dependencies at the expense of perhaps requiring a separate Underscore from the main project?)

I think the lesson learned here is "don't use ~ or ^ when pulling in Backbone via package.json"

yep.

I think the lesson learned here is "don't use ~ or ^ when pulling in Backbone via package.json"

I've outlined above why this should not be the takeaway lesson.

I think the lesson learned here is "don't use ~ or ^ when pulling in Backbone via package.json"

That's what you do, as a consequence, to protect your code from breaking.

The lesson would be more like "following semver is good for everyone, not doing so is not."

I can appreciate the value in "romantic" versioning. Too bad they don't coexist very well.

Should be noted that there will always be projects that don't follow semver very strictly, and those that attempt to but fall short, so the system always leaks a little.

At least Backbone is generally very good about not breaking things.

@dgbeck things break all the time per versions see my earlier comment


So I think the value in following semver that has not really been talked about is the fact that you guys can push minor features and bug fixes and allow people who depends on it upstream to get these changes for free.

To me this is a great value add but obviously this comes at the cost of complexity for the maintainer.

Was this page helpful?
0 / 5 - 0 ratings