-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document version compatibility goals #1233
Comments
Just my 2 cents. |
In my view, version numbers are cheap but compatibility promises are valuable. I would go for something closer to semantic versioning: After 1.0.0, changes mean: Usually, you can avoid breaking binary compatibility by making some slightly different choices and since we hope for wide adoption, each binary break is a huge downstream cost we often don't see. Especially as cats is adopted by other libraries, so that it is often a diamond dependency. I'm a huge advocate of making some compromises to keep binary compatibility. I think this comes down to goals: my goal is adoption and impact (there are other goals, such as demonstration, teaching, etc...). With adoption means people will want to use N libraries, they will all want slightly different cats, and so most build tools will give them the largest version number. We should work very hard to make that almost always compatible. |
@johnynek are there examples of other prominent libraries in the scala ecosystem using that sort of versioning scheme? Out of all of the libraries that I've had to worry about version compatibilities in recent years (scalaz, shapeless, akka, scodec, scala itself), minor versions track binary incompatibilities and major versions track significant changes to the library (rewrites, major overhauls, etc). I don't have any super strong opinions on versioning, but I also don't want to go against the grain and confuse users. |
related to #608 |
There are two popular versioning schemes here:
Both only breaks bin compat at major versions. IMO, it's basically a trade-off between the ability to release Most other scala libraries I know are using the java/scala style. But Akka changed the versioning scheme to semantic versioning since 2.4 possiblly because that like I am not sure if one is strictly more suitable to cats than the other. I propose we just hold a vote and move forward with the decision. |
semver |
When talking of How many changes does it take for us to consider that an My problem with So I vote for "semver". It's awful, but it's the standard way to communicate breakage. |
I lean toward @johnynek's proposal because it makes use of the full namespace and is defined in a way that could be automated, at least in principle. It makes it harder to indicate rewrite-scale breakages but these are so infrequent in practice we can indicate them in some other way, like jumping up the next round 100 or something. |
Semantic™ or otherwise, version number is a A third option you might want to consider is using
This allows |
In my opinion, I think it's best to follow pure semver:
I think that this versioning scheme covers all the cases and helps represent the various ways in which developers of a library can break users' code. For everything that rests undefined, semver defaults apply. |
@johnynek can you say why binary compatible additions are excluded from your patch level? As @ceedubs mentioned above, shapeless's scheme is epoch.major.minor where minor level makes binary compatibility guarantees; major level makes hand-wavey design consistency promises and at epoch level all bets are off. |
Here is the definition of |
@eed3si9n I vote for using org to differentiate bincompat breaking versions as well. We don't have to decide that for now, it can be delayed until we plan the first bincomp breaking 2.0 release right? What I am suggesting is that for 1.0 we could continue use |
The actual organization name is a minor variance (though I think As @johnynek said:
With the |
I'm very uncomfortable with the idea of using the organization id to distinguish versions ... this will play badly with tools (eg. publishing to Sonatype under a new organization id would need the new organization id to be registered and maintainers granted permissions all over again) and policies (eg. I can imagine that changing an organization id might mean that an artefact would have to go through corporate approval processes again in a way that wouldn't be necessary for a simple version bump). |
Oh, and it's also "odd" ... I'm not against doing things differently per se, but I think that this stuff has been around for long enough that we ought to be able to point to a successful precedent. |
It (changing org) definitely has a higher one time cost than simply bumming up the major version number. I am still in favor of it because
I don't think using org rename system should change stability expectation though. The org rename system only helps if the cats dependency remains internal to a lib, i.e. cats type classes and data structures do not appear in the public API of the lib. But the opposite is probably more common. For new binary breaking features, we can introduce them with a new module, or at a new major scala version. For example, we should be able to introduce 2.13 enabled bin breaking changes in a |
I don't know if See for example Java Interoperability Policy for Major Version Updates:
Edit:
|
Another related data point I came across is Google's Cloud APIs Versioning.
....
|
One good presentation arguing for breaking backwards compatibility only with a namespace rename is the Spec-ulation keynote by Rich Hickey. |
@alexandru Thanks for sharing this. Really enjoyed watching it. |
i've just learned of this tool, by the way: https://github.com/lvc/japi-tracker looks really interesting. Instead of telling you yes/no compatibility it can give a score (what fraction of methods have incompatible changes). This can be interesting to consider too, since too often when we have incompatibility for a good reason, we go overboard making many incompatible changes which is pain multiplied by the number of adopters. Even when we have incompatibility, we should strive for small incompatibilities. Here's an example of the output: |
Looks like the vast majority voted for semver. There are still some debate over whether to use org name to mark breaking versions. I think we can delay that decision when we reach the breaking point - hopefully that will be a while. If no objections, I am going to submit a PR to document the semver binary compat goals in README. |
* add bin compat goal fixes #1233 * Update README.md * correct typo * fix typos
This might be pedantic, but #1897 only addresses binary compatibility, while the original description of this issue also talks about source compatibility. (And I wasn't able to determine from the discussion what's the current consensus about that.) |
Binary compatibility implies source compatibility, but not vice versa. Source compatibility is less important in the context of Scala, since the compiler can help pinpoint the changes that need to be made and you can also have automatic rewrite rules defined with Scalafix. Migrating a codebase to a new version that breaks source compatibility may be costly, but at least it's a deterministic process, since you've got the compiler and your tests guarding against regressions. But binary compatibility is where it hurts, since in testing you're not testing transitive dependencies and when the JVM links at runtime to the JARs indicated by the classpath, the compiler is not involved at all. Note that for dynamic languages (that get distributed as source, instead of compiled binary JARs), binary compatibility == source compatibility. |
Not really. Here are a few examples of binary compatible but source incompatible changes. |
Just created #1907 |
To the best of my knowledge, no, it does not. |
I'm not sure I agree that these are "accidental". For example the BTW, I agree that in practice source compatibility is not a big concern, so I'd be OK with simply adding a sentence that "We don't really care about source compatibility" (or similar :-). However, I think that the documentation (as it currently stands) is ambiguous (regarding binary/source compat); that's why I raised this question. (Maybe we should continue this discussion at #1907?) |
Agree we should continue the discussion at #1907 |
I think that we should document what our goals are with respect to binary/source compatibility as we reach 1.0.
I'd be inclined to propose the following:
1.0.2
is binary compatible with1.0.0
and1.0.1
.1.1.0
is not necessarily binary compatible with1.0.0
.cats-kernel
module will remain binary-compatible across minor versions. Binary-incompatible changes to this module should only occur alongside a major version bump (which will be few and far-between).What do people think about the ones I have? Are there others that we should add?
One thing that I don't really know how to quantify is source-compatibility. In general I want us to strive for source-compatible changes, but as long as they aren't too intrusive, I think it's less of a concern than binary compatibility.
cc @johnynek and @mpilquist who I think are both interested in compatibility.
The text was updated successfully, but these errors were encountered: