
Fix the versioning - abritishguy
https://github.com/jashkenas/underscore/issues/1805
======
hawkice
I am concerned the primary purpose of this being on the frontpage is shaming
someone.

I'm a big fan of semver, but I also test whenever I do a rm Gemfile.lock;
bundle install (I've only managed a fairly small nodejs app in production, but
I'd be surprised if people really don't test something like that). So he did
something we think is bad -- but plenty of beginning engineers do this all the
time, and while the discussion on github is appropriate, I'm not sure it
belongs here on HN. People shouldn't be afraid of making something useful (as
underscore is) because of the potential for extremely public shaming.

~~~
abritishguy
This is the most depended upon node module on npm, this is not some beginner
engineer - I think this belongs here.

~~~
hawkice
If the purpose is to alert people to perhaps subtle bugs in their code, then
clearly it's relevant to the engineers here.

But if your point is that we should publicly highlight mistakes (or things we
don't like) in packages because we expect people to do better... then I guess
I should step out of this conversation. I don't want to talk highschool about
someone building cool things.

~~~
akerl_
The connection between a project's developers and its community is noteworthy
and worth discussing.

As a developer, how you treat your user base is relevant, and has a real
impact on the value of the thing you have produced. We have successful
projects whose leaders vary wildly in style, from Linus's approach to kernel
development to projects that delegate final code control to community
contributors.

Talking about the human elements that factor in to technology has merit;
talking about the best ways to handle a project's community has merit. It's
not "talk[ing] highschool".

------
tylerlh
This feels like an overly abrasive response that makes me seriously question
whether using Underscore moving forward is a good idea. I really hate to say
that because I think Jeremy's projects are awesome.

This is the most depended on module on npm. Why are you so intent on
alienating the package consumers? IMO, having a version 47.0.0 and such
doesn't seem all that terrible to me, and is still just as human readable.
Other groups are doing it and it's working just fine (ie Chrome).

~~~
jessaustin
_...having a version 47.0.0 and such doesn 't seem all that terrible to me..._

What would the effect of that be? Since few people are silly enough to use the
">=" operator in _package.json_ , a popular package with that many "breaking"
changes is effectively going to be pinned at 46 different points. I imagine
we'd start to see some of the same entitled whinging we see exhibited here,
but in the opposite direction. "Why do you have so many major releases? It
means I have to re-release my packages constantly."

~~~
tylerlh
That's a fair point. I guess a better solution in my mind is teaching people
to be more responsible with their package.json file and consumption of
packages (ie reading changelogs), but that's not jashkenas' problem, nor
should it be.

~~~
jessaustin
Actually I think he's done quite a bit of teaching along those lines in the
last three days. Several students seem unhappy with the lesson...

------
thinkbohemian
1) Semver is hard. I've got publicly used libraries with millions of downloads
and sometimes people use it in ways I don't expect and this results in
breaking backwards compatibility. Most large projects aren't, or can't be true
semver. Take for example Rails. This is a great discussion over an area over
why breaking semver may be better than keeping it in one case:
[https://github.com/rails/rails/issues/16497](https://github.com/rails/rails/issues/16497)

2) Breaking semver sucks, and I go hulk rage mad when my shit breaks.

~~~
abritishguy
Totally agree, however I feel there is a difference between choosing to break
semver for a specific reason rather than a complete disregard for it.

Semver should be based upon the public API - if a dependent module is using
undocumented stuff then they should pin the version down.

------
jessaustin
It takes a certain _chutzpah_ to leave the sort of comments one sees on this
issue and the similar one for Backbone. The author hasn't made a secret of his
versioning policy. If you have a broken module, you shouldn't have used [EDIT:
actually "~" would have been fine] "^" or (my favorite) ">=" as a semver
operator when depending on this module on which you depend for free. Anyway,
with a decent test suite, surely a modicum of (automated) testing has already
identified the pinning that should take place?

~~~
abritishguy
>The author hasn't made a secret of his versioning policy.

No one is going to see that unless they go looking for it though

>you shouldn't have used "~", "^"

That is how the npm ecosystem works, and in any case the issue arose from
dependencies that in turn depended on underscore and thus are not under my
direct control.

> Anyway, with a decent test suite, surely a modicum of (automated) testing
> has already identified the pinning that should take place?

My particular issue is in a new project I could not install several
dependencies as npm downloaded the newest compatible version which was
supposedly 1.7.0 - the only way to fix this is to manually create a lock file.

>you depend for free.

True, and I'm tremendously grateful for all the work that has gone into it and
it would be a massive shame if that work was for nothing if a continued
disregard for semver forces people to switch to lodash.

~~~
jessaustin
_...dependencies that in turn depended on underscore..._

Do you imagine that the maintainers of all these dependencies are going to
catch any fraction of the hell that jashkenas seems to be catching for this?
It's just as much their fault as it is his. Why don't they pin and test?

~~~
abritishguy
Because that is not the convention in the ecosystem - npm mandates the use of
semver - if you follow it this can't happen. If you do what you say and pin it
down to an exact version then you would have to release an update every week
consisting of just a version bump.

~~~
jessaustin
Don't stop there: think it all the way through! Breaking changes lead to
version bump releases, whether the module follows semver or not.

[https://news.ycombinator.com/item?id=8244888](https://news.ycombinator.com/item?id=8244888)

Do you mean to imply that breaking-change frequency should stay below some
particular maximum value? That argument is completely unrelated to the use or
disuse of semver.

------
gojomo
The title-as-submitted ("Underscore.js author breaks 100s of modules because
of a disliking of semver") is unnecessarily personalizing and editorializing.
I'd suggest a title of just the facts: "Underscore.js 1.7.0 breaks modules by
rejecting semantic versioning". (The native title, "Fix the versioning",
contains insufficient detail to convey either the important warning-to-
Underscore-users nor reflect the issues discussed.)

This issue highlights an interesting philosophical split.

I suspect the same minimalist, intentional aesthetic that has made Ashkenas's
projects so beloved equally drives his dislike of version-inflation, whatever
its convenience is to downstream systems on autopilot.

~~~
kudu
> The native title, "Fix the versioning", contains insufficient detail to
> convey either the important warning-to-Underscore-users nor reflect the
> issues discussed.

Incidently, this is the title the mods chose. Can anyone guess how many spots
the link dropped on the front page after that change?

------
seliopou
The only major version bump that matters is the one from 0 to 1. After that,
the project is better served if its maintainers do not fetishize major version
numbers, or any version numbers for that matter, and realize that they're
there to facilitate automation, not to satisfy some sense of human aesthetics.

------
jashkenas
If the asshole responsible for this mess can chime in for a moment ;)

I figured that it was worth a bit of a longer explanation (cross-posted from
[https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e))

\---

Spurred by this thread, here's is a quick set of jotted-down thoughts about
the state of "Semantic" Versioning, and why we should be fighting the good
fight against it.

For a long time in the history of software, version numbers indicated the
relative progress and change in a given piece of software. A major release
(1.x.x) was _major_ , a minor release (x.1.x) was _minor_ , and a patch
release was just a small patch. You could evaluate a given piece of software
by name + version, and get a feeling for how far away version 2.0.1 was from
version 2.8.0.

But Semantic Versioning (henceforth, SemVer), as specified at
[http://semver.org/](http://semver.org/), changes this to prioritize a
mechanistic understanding of a codebase over a human one. _Any_ "breaking"
change to the software must be accompanied with a new major version number.
It's alright for robots, but bad for us.

SemVer tries to compress a huge amount of information — the nature of the
change, the percentage of users that will be affected by the change, the
severity of the change (Is it easy to fix my code? Or do I have to rewrite
everything?) — into a single number. And unsurprisingly, it's impossible for
that single number to contain enough meaningful information.

If your package has a minor change in behavior that will "break" for 1% of
your users, is that a breaking change? Does that change if the number of
affected users is 10%? or 20? How about if instead, it's only a small number
of users that will have to change their code, but the change for them will be
difficult? — a common event with deprecated unpopular features. Semantic
versioning treats all of these scenarios in the same way, even though in a
perfect world the consumers of your codebase should be reacting to them in
quite different ways.

Ultimately, breaking changes are no fun, and we should strive to avoid them
when possible. To the extent that SemVer encourages us to avoid changing our
public API, it's all for the better. But to the extent that SemVer encourages
us to pretend like minor changes in behavior aren't happening all the time;
and that it's safe to blindly update packages — it needs to be re-evaluated.

Some pieces of software are like icebergs: a small surface area that's
visible, and a mountain of private code hidden beneath. For those types of
packages, something like SemVer can be helpful. But much of the code on the
web, and in repositories like npm, isn't code like that at all — there's a lot
of surface area, and minor changes happen frequently.

Ultimately, SemVer is a false promise that appeals to many developers — the
promise of pain-free, don't-have-to-think-about-it, updates to dependencies.
But it simply isn't true. Node doesn't follow SemVer, Rails doesn't do it,
Python doesn't do it, Ruby doesn't do it, jQuery doesn't (really) do it, even
npm doesn't follow SemVer. There's a distinction that can be drawn here
between large packages and tiny ones — but that only goes to show how
inappropriate it is for a single number to "define" the compatibility of any
large body of code. If you've ever had trouble reconciling your npm
dependencies, then you _know_ that it's a false promise. If you've ever
depended on a package that attempted to do SemVer, you've missed out on
getting updates that probably would have been lovely to get, because of a
minor change in behavior that almost certainly wouldn't have affected you.

If at this point you're hopping on one foot and saying — _wait a minute, Node
is 0.x.x_ — SemVer allows pre-1.0 packages to change anything at any time!
You're right! And you're also missing the forest for the trees! Keeping a
system that's in heavy production use at pre-1.0 levels for many years is
_effectively the same thing as not using SemVer in the first place_.

The responsible way to upgrade isn't to blindly pull in dependencies and
assume that all is well just because a version number says so — the
responsible way is to set aside five or ten minutes, every once in a while, to
go through and update your dependencies, and make any minor changes that need
to be made at that time. If an important security fix happens in a version
that also contains a breaking change for your app — you still need to adjust
your app to get the fix, right?

SemVer is woefully inadequate as a scheme that determines compatibility
between two pieces of code — even a textual changelog is better. Perhaps a
better automated compatibility scheme is possible. One based on matching type
signatures against a public API, or comparing the runs of a project's public
test suite — imagine a package manager that ran the test suite of the version
you're currently using against the code of the version you'd like to upgrade
to, and told you _exactly_ what wasn't going to work. But SemVer isn't that.
SemVer is pretty close to the most reductive compatibility check you would be
able to dream up if you tried.

If you pretend like SemVer is going to save you from ever having to deal with
a breaking change — you're going to be disappointed. It's better to keep
version numbers that reflect the real state and progress of a project, use
descriptive changelogs to mark and annotate changes in behavior as they occur,
avoid creating breaking changes in the first place whenever possible, and
responsibly update your dependencies instead of blindly doing so.

Basically, __Romantic Versioning __, not Semantic Versioning.

All that said, okay, okay, fine — Underscore 1.7.0 can be Underscore 2.0.0.
Uncle.

(typed in haste, excuse any grammar-os, will correct later)

~~~
munificent
I appreciate your thoughts as always. I'm sure this is frustrating for you
because you have a bunch of users yelling at you to do something in a way you
don't agree with, and it's not like they _pay_ you for the right to do that.

A couple comments:

> Node doesn't follow SemVer, Rails doesn't do it, Python doesn't do it, Ruby
> doesn't do it, jQuery doesn't (really) do it

Node does (because it's <1.0.0 where semver's rules are different). Everything
else you list is older than semver, so short of a time machine or a radical
change to their long-established versioning policies, there's not much they
can do.

> the responsible way is to set aside five or ten minutes, every once in a
> while, to go through and update your dependencies, and make any minor
> changes that need to be made at that time.

That works fine for your _immediate_ dependencies. The reason why I think
things like semver are important is that the above doesn't work at all with
transitive dependencies.

If my app uses foo which uses bar which uses baz and the maintainers of baz
decide to make a breaking change in a minor version, I'm not in a happy place
when that wolf in sheep's clothing appears in my dependency graph. I'll see
that my app is broken, but unless I want to fork bar and maybe foo and start
mucking around in code I've never touched before, my options are pretty
limited.

I don't think semver is perfect, but I find it does make transitive and shared
dependencies a lot more reliable to work with. I'm willing to sacrifice human-
meaningful version numbers to get that.

~~~
krebby
> Node does (because it's <1.0.0 where semver's rules are different)

You might've missed the paragraph preëmptively responding to that (it was
added in an edit).

SemVer says that you shouldn't be pre-1.0.0 if you're actively used in
production anywhere. Node has been out for years. Treating the current
versions of Node as pre-1.0.0 is a joke.

From the semver.org FAQ:

> How do I know when to release 1.0.0?

> 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.

Node definitely applies.

~~~
sturadnidge
There is no way an author / project can control when someone is going to use
their software 'in production', I would certainly argue that condition is the
weakest of indicators as to whether something is 1.0.0 or not.

Aside from that, the other 2 indicators definitely do not apply to Node (API
is not stable, there is not a lot of worry about backwards compatibility as
you'll see in the upcoming 0.12 release).

So no, Node is not '1.0.0' according to SemVer.

------
ricardobeat
The blame for this falls squarely on NPM for replacing the default ~ (update
patches) with ^ (update minor versions).

The only reason for having automatic package updates in the first place is to
receive bug and security patches. There is little gain in receiving 'minor'
updates if you are not changing your code, and any serious project will end up
freezing the dependency tree anyway.

~~~
jessaustin
Is this ironic?

[https://github.com/npm/npm/releases/tag/v1.4.3](https://github.com/npm/npm/releases/tag/v1.4.3)

[look at the patch number...]

------
shadeless
I'm a bit surprised no one has mentioned FerVer(Fear-Driven Versioning) yet,
it was made in an effort to fix exactly this kind of problem. [1]

[1]
[https://github.com/jonathanong/ferver](https://github.com/jonathanong/ferver)

------
wprl
It's really not that hard.

If you have a lot of breaking changes, you probably shouldn't be at 1.x.x. If
you need to deprecate something, add the extra features alongside and remove
the deprecated features in the next major release. If you need to add
something to code that is >= 1.x.x and you think it will need breaking
changes, you should mark the feature as experimental in the documentation
until it has stabilized. Semver works great for humans and robots if you put a
smidgeon of planning and consideration into the process!

------
eldude
Simple, add an optional human significant "ultra" version (better name
suggestions welcome) to indicate a philosophical version upgrade consistent
with how major versions have historically been used (as marketing
communications).

E.g., 1.1.7.0 or 1.7.0 are equivalent.

[Cross posted from the other thread:
[https://news.ycombinator.com/item?id=8244920](https://news.ycombinator.com/item?id=8244920)]

------
QuantumChaos
Can someone outline who the people arguing against Jeremy Ashkenas are?

It would make a big difference if they were ordinary users, vs maintainers of
other important libraries of pieces of software.

While everyone deserves their say, this issue seems somewhat subjective, and a
package maintainer shouldn't have to pay undue attention to individual users
who don't necessarily represent the whole community.

------
Lavinski
This link ([http://www.jongleberry.com/semver-has-failed-
us.html](http://www.jongleberry.com/semver-has-failed-us.html)) was also
posted on HN a while ago.

HN:
[https://news.ycombinator.com/item?id=8154933](https://news.ycombinator.com/item?id=8154933)

------
krebby
See also
[https://github.com/jashkenas/underscore/issues/1684](https://github.com/jashkenas/underscore/issues/1684)

------
ascendantlogic
It takes the same amount of effort to type "2.0.0" as it does "1.7.0" but the
effects of this choice are obviously much larger. Why is it such a roadblock
to not break everyone else's code?

~~~
kalleboo
It sounds like the maintainers reasoning is "pretty much every version is
going to break something somewhere"

~~~
sethammons
That is where I get lost. What is wrong with that?

