Hacker News new | past | comments | ask | show | jobs | submit login
Fix the versioning (github.com/jashkenas)
115 points by abritishguy on Aug 29, 2014 | hide | past | favorite | 78 comments

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.

The larger discussion about whether or not package maintainers have a responsibility to minimize user frustration at the cost of their own opinions and practices is worthwhile.

If I'm the author of an unpopular module, where I am the sole user, and I don't like semantic versioning or some other facet of package management, I don't follow it. Should I be expected to change my stance just because other people begin using my project? At what point is my project's community large enough that maintaining a healthy ecosystem involves sharing some control over the practices with that community?

It also doesn't help here that rather than having a rational discussion, the author released what can only be described as a troll package, where every version change becomes a major version. Using that would be the height of insanity, as noted in the issue thread, because all libraries would need to update their dependencies and re-release with every Underscore-semver release, due to dependency version conflicts.

> It also doesn't help here that rather than having a rational discussion, the author released what can only be described as a troll package, where every version change becomes a major version.

What exactly about Jeremy Ashkenas makes you think this was done as a way to troll people? He still took a lot of time to make release notes and note all of the changes.

I was referring specifically to the underscore-semver package, not the Underscore project as a whole. Using it in actual projects isn't feasible in any way, because it would require that your project and any project you depend on that also depends on underscore-semver specify the exact same version, or else we're back with the same problem as before. And since you won't be a package maintainer for everything your depend on in most cases, that isn't feasible.

He's not released a version that obeys semver, he's released a version that treats any update as a breaking change.

Ah, I didn't realize you were talking about underscore-semver. I'm sure that was done tongue in cheek.

> He's not released a version that obeys semver, he's released a version that treats any update as a breaking change.

SemVer isn't a law. It's a set of guidelines for versioning software in a slightly less arbitrary way. Maybe extra precaution could be taken for something as common as underscore, and to me that is the only argument worth having here.

Maybe I'm biased by not having a widely used open source project, and my judgement is thus clouded by wanting to one day have a community of users for something that I've written.

That said, I do write code and have tools that are used by other groups of people, and have experienced feature requests and suggestions and patches that I don't necessarily agree with, and I've always tried to step back and consider the overall impact on the project rather than my personal preconception of what the project "should" be. I've merged features that I'd never use and adjusted things to make my project more friendly for users who aren't me.

I think that one of the greater things about open source projects is that over time the original author can focus more on the fun parts or on guiding the overall direction of the project, because the community can provide assistance with identifying issues and maintaining existing systems. Whether the version number is 2.0.0 or 1.7.0 or 50.0.0 is such a trivial thing, and as a developer I'd imagine I'd make my choice based on what made my project more usable for the community.

I think underscore-semver is "ha, ha, but serious". It does fix the problem of protecting people from what might be breaking changes, while freeing the author from having to carefully track changes. It implies: you should upgrade your Underscore if and only if you've made a conscious, aware decision to do so.

I think it's OK for an open-source project – a freely-offered gift to the world – to take that approach, if the author prefers to be personally indifferent about "breaking changes". It's a sort of technical declaration of "NO WARRANTIES", specifically no warranty of "FITNESS FOR A PARTICULAR PURPOSE" – that purpose being, "painless drop-in where a previous version was used".

Yes, but due to the nature of dependencies, it becomes crazy to use in practice. Imagine I write "leetapp", and it depends on "underscore-semver 170.0.0", "tablething 1.0.0", and "otherstuff 2.1.3". Except tablething also uses underscore, so it too depends on "underscore-semver 170.0.0". Now Underscore puts out a new version. I cannot update my app to use 180.0.0 until tablething's devs also do so, or else our dependencies will not be resolvable. This isn't too bad if I only have one dep, but what if I have 20 dependencies that all, somewhere in their dependencies, need underscore-semver?

This is the reason that semver and ranges of dependency management became useful in the first place, because I can say that leetapp needs underscore-realsemver (1.6.0-1.6.n), and tablething can say it needs version (1.6.3-1.6.n) and so forth. This works with sane semver because we can use the parts of the version string to agree on the major API while allowing bugfixes and other improvements to happen without every project needing to bump version numbers.

It depends on what package manager you are using. NPM would allow tablething to use 170.0.0 while leetapp used 180.0.0. Most of the discussion about underscore has been in the context of NPM. Of course your point still stands, because underscore is available in many other package managers, and is very often used without a package manager at all...

The Underscore-semver package is a bit of a troll package — it's the literal-minded SemVer way of versioning Underscore.

Historically, nearly every single release has had at least one thing that mildly changed the behavior of some minor edge case or other. So by strict SemVer, if we wouldn't be at version "170.0.0" by now, we'd be damn close to it.

Why does that matter? Are big numbers inherently bad?

A maintainer did that.

Yup. I'm the contributor who wrote that pull for the release. You can see the original here https://github.com/jashkenas/underscore/pull/1799

Well, I'm glad this got to frontpage. I don't know if the purpose was shaming someone (it didn't even cross my mind) but it made me reflect on how my versioning affects others.

I knew this was going to happen when NPM went from default ~ in dependencies (update only patches) to ^ (update minor versions). In fact, I changed my default back to ~ out of fear this would happen.

I think the problem is that it completely halts development of anything that uses a module that uses underscore (or even a module that uses a module that uses underscore, ad infinitum) since many modules have their dependencies written in such a way that npm will install 1.7, despite it not being compatible. This seems important enough to be something of a public-shaming.

edit: Please comment saying why you disagree, rather than simply downvoting.

"Public shaming" of someone who's been as productive and generous with his open-source work as Ashkenas is never appropriate.

Respectfully disagree on the particulars, sure, but don't imply that someone who's given you a gift now owes you extra work, when their own design sense – the same thing that created the shared bounty – guides them otherwise.

People should also consider that authors of popular projects are inundated with support requests and demands for their time, and have to set some boundaries on their efforts, which may appear callous to outsiders. If his boundary here is not wanting to embrace Semantic Versioning, respect it, and fork/migrate/workaround rather than whine/shame/guilt.

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

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.

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

We could also submit a link to your issue on GitHub with the title "Engineer Mindlessly Updates Dependencies and Deploys Without Testing, Shocked to Learn Application Doesn't work."

I started a new repo and wanted to know why several of the dependencies were not working, only way to fix it was to manually change the underscore version number in these dependencies - obviously you wouldn't just push an update to production without testing it.

I think you'd find that it falls off the front page pretty quickly.

Yes. Not that I had any plans to write node modules, but I sure as fuck don't want to now, lest somebody discover my work and start using it and then telling me how I need to do things.


_ is the most depended on node.js module. Maintainer, Ashkenas, introduced breaking changes. By default npm will pull down these changes without prompting because it was designed to follow semver. Maybe npm is at fault. Maybe it's Ashkenas.

However, Ashkenas knows his change is going to break people and just doesn't care.

Did the same thing not happen with 1.6? And 1.5? Who thought 1.7 would be different?

Or perhaps the fault lies with the people who update their dependencies blindly and then don't run tests. Not locking your dependencies down is a recipe for breakage.

I suppose I shouldn't start new projects, either?

How does that follow?

When you started a new project and pulled down new packages, all the packages that depended on underscore functionality that changed were broken because of this change. That's because NPM makes assumptions about major/minor versions and those packages pulled down the incompatible version.

You can suggested that every package on npm vender their own dependencies, but in practice nobody does this because npm is known to make these assumptions.

Sadly, Jeremy Ashkenas is not a beginning engineer. He's just acting like one (or just trolling and wants everybody to switch to lodash).

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

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

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.

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

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

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

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.

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?

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

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

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.

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


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.

For nothing? So something that is used only temporarily is worthless? If you didn't have to write boilerplate or your own functional library because underscore existed at some point, you had a net gain in productivity and was able to release your own code faster, regardless of whether you eventually end up switching.

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.

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

I agree, looks like a mod has changed it anyway.

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.

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)


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/, 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)

> For most of software history, 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 a small patch. You could evaluate a given piece of software by name, 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/, changes this to make a mechanistic understanding of a codebase more important than a human one. Any "breaking" change to the software must be accompanied with a new major version number.

I'm about 80% sure you're mistaken on this. I don't have a spec document or an example to back me up, but I've been slinging code for almost 30 years now, and cut my professional teeth on a big Unisys mainframe. Before version numbering in software became totally subjective, they were used to indicate break/change/patch, as described in semver.org.

It was later on that software projects started to move away from that, mostly shareware and desktop software in the 90s, and only recently that projects like Firefox entirely lost the plot.

The reason that "semver" used to be so popular, as you note, is because it made enterprise IT manageable. Developers don't think about that much anymore though; they just expect big IT departments to roll out nightly updates and then deal with the fallout the next day.

(I'm not piling on or picking a fight, I don't use Underscore, I don't have a horse in this race. I'd welcome cited corrections or opinions from even older developers.)

Every date-based Firefox update breaks compatibility with binary add-ons (ones that link to the libxul.so C++ library). According to both SevMer and traditional library versioning practices, incrementing the major version is the correct thing to do in this case. I'm not sure why you say it has "lost the plot."

Application software has generally used version numbers in different ways from library software. It's tricky for products like Firefox that are both application and library.

I must be missing something.

I was under the impression that Mozilla was incrementing Firefox's major version number with every new release, even if new releases didn't have api changes. As described in http://jonoscript.wordpress.com/2011/07/18/its-not-about-the... for example.

Is that not the case? Is there actually some part of Firefox that other software relies on that's getting changed in not-backwards-compatible ways with every release?

For normal extensions that use supported JavaScript APIs, most releases will not break any APIs. The blog post you linked to is talking about the compatibility process for these normal JS extensions.

But there is a special class of extensions ("binary add-ons") that link to Firefox/libxul as a C++ library. This has been discouraged for a long time now, but still supported for legacy reasons. These extensions have full access to Firefox's internal C++ and XPCOM interfaces. Since Firefox 4, the ABI of this internal library changes with every major update, so every release is breaking for binary add-ons (except security patches, which take care not to change the ABI, and also do not increment the major version). This is mentioned briefly in the comments of the blog post you linked to.

Since that blog post was written, Firefox's add-on system has changed to address this dichotomy. Non-binary add-ons new use "lax" version checking by default (a minimum Firefox version is checked, but no maximum), while binary add-ons still use "strict" versioning. This is documented here:



[disclosure: I'm an developer at Mozilla.]

Thanks for the explanation. It cleared up some misconceptions. I'll bookmark this for future reference.

I sort-of think it's this guys library -- so he can change the major version number whenever he wants. Heck -- the Kernel project (now) just changes versions whenever they "feel it's right", and nobody complains... API changes or not.

Yep. I wasn't arguing for or against one religion of version numbering or another, just trying to clear up some of the history of it.

I wouldn't offer my opinion on version numbering anyway, since my opinion isn't worth anything. It's definitely not in my own interest to argue for sane version numbering schemes; clients pay me hourly rates to fix issues with the software they use.

I think the big problem with semver is point 2 in their summary: "MINOR version when you add functionality in a backwards-compatible manner"

That may make sense for very large software projects or operating systems where backwards compatibility is a huge concern, but it's not a good fit for the majority of software projects. This is especially true when these projects aren't compiled and thus don't even have an ABI to worry about.

This view on versioning I think comes from a time when most software was compiled and when compiling that software would take a _long_ time or require downtime; thus protecting ABI compatibility was worth the effort.

For modern projects that are in an interpreted language, I think constraining the middle version number to "non-breaking" changes is silly as it's copying a concern that no longer applies. It forces you to choose between "bug-fix" and "feature" releases and pace your project development in a rigid fashion that may not make much sense.

Also, I think it's ridiculous to require anything other than big-fix releases to be non-breaking in the first place. If 1.6.x worked for you, why are you even trying to use 1.7.x if not to access new features? If that's the case, you're going to be editing your code again anyways.

Worrying about a release manager automatically pulling a 1.7 codebase to upgrade a 1.6 codebase is silly; why is the package manager doing this in the first place?

Having both MINOR and PATCH to mean non-breaking changes really seems excessive and based on very large waterfall-based software projects, because for most open source development it's completely arbitrary whether to bump patch or minor. I think it would be far more useful to have both MAJOR and MINOR to signify breaking changes (with MAJOR being close to the romantic versioning that Jeremy alludes to, where the software effectively enters a new phase.) And a number like 1.7.247 is more intelligible than 170.2.5, and really, if you're the rare monolithic long release-cycle software project, just use an extra number after PATCH. It's not like there'd be an acute concern over the verboseness of that version number internally compared to all the other highly bureaucratic processes going on in the organization.

I interpret PATCH as "no change in the intended semantics, just a bug fix". Occasionally that's still ambiguous, when the bug was in the intended semantics, but I'm not sure that's a big problem. When adding new functionality, I prefer to see MINOR bumped, even if small.

Just one opinion, of course.

What are your thoughts on splitting the SemVer "major" version number into two parts? Calling a change that will not break any code "major" seems... unlikely (though I guess I could be wrong about that?). If that's the case, then from W.X.Y.Z, "breaking change but won't effect too much, easy enough to update" bumps X, "entirely rethought the model, updating will be a pain" bumps W, "won't even break your code but we added some stuff" bumps Y, and "non-breaking bugfix" bumps Z (and I think "bugfix, but might break some stuff" probably bumps X). That should provide space enough to communicate both the mechanistic and a meaningful summary of the humanistic (with change logs for more detail, as ever).

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.

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

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.

Part of what I'm saying is that your transitive dependencies shouldn't be changing willy-nilly in the first place. The code you depend on is ultimate code you're responsible for — and having changes happening deep down that you're not aware of is a recipe for trouble.

Immediate dependencies are a relative thing, after all — foo's deep dependency is bar's immediate dependency. And if SemVer'ing them only works some of the time, but won't save you all of the time, then why bother pretending in the first place?

The actual appearance of breaking changes in software that end up affecting you occurs at the same interval regardless of the version number we decide to label them with. We can do better for determining compatibility than a three or four character version number.

I can accept everything you have written here - my feelings towards semver are very similar to your own. I feel in this instance what transpired was a deviation from what you have written - I went to start a new project and 2 of the dependencies I installed (out of 10) had problems, this release changed a lot of stuff that affected many of the dependent modules.

>If the asshole responsible...

If anyone was the asshole it was me, however I truly believe that underscore is better off and I would like to thank you for all the work you have put into it. :)

There is great benefit to being able to bump your dependencies in a consistent manner. Specifically:

* We want to be able to easily pick up non-breaking bug/security fixes that should not cause us to change code.

* We want to be able to pick up newer features, and are ok to make changes to our own in response.

In both cases, we need to be confident about which sort of upgrade we are getting.

Semver gives that; it's just unfortunate that it doesn't map to the human notion of what a major version is.

Jeremy, you make some great points here and I agree with you on most of them -- it's just that Underscore doesn't seem like the right place to start the battle.

Why is it not the right place? Why do people even have to update underscore--just keep with the older version. They also have a mostly drop-in replacement in lodash (well, last I've seen, at least). So I think it's a perfectly good place, it's not a library of "shiny new features", rather a staple that most people probably don't need to update, and even has an alternative.

And you don't fight battles without a deal of incoveniencing. The mere fact of the publicity this is generating makes it a fair ground to fight that battle. Which is to say I can see his position, despite liking semver myself--though it could be distilled into a better standard and that could be a net positive long term on software development that far offsets the man-hours now being lost.

You know what they say...opinions are like assholes...

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.

Is this ironic?


[look at the patch number...]

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

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!

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., or 1.7.0 are equivalent.

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

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.

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?

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

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

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact