Skip to content
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

Libraries that potentially break backwards-compatibility should not be brought in via "provided" #183

Closed
timcharper opened this issue Jul 21, 2015 · 9 comments

Comments

@timcharper
Copy link
Contributor

Using "provided" for terrible, because SBT does not have a chance to tell you that there is a version incompatibility, and this is critical (IE - I have play-json 2.3.x, but slick-pg uses 2.4.x). I would motion that it be moved back to the way it was.

Since Joda time is no longer under development, there is little risk there. But for integration with play-json, json4s, argonaut, etc. - backwards compatibility is broken with each minor version bump.

What can compound this issue is if these libraries depend on versions of other libraries that conflict.

@tminglei
Copy link
Owner

So, what shall we do?

@timcharper
Copy link
Contributor Author

I've had a night to sleep on this, and I'm feeling slightly less passionate against the "provided" approach because the backwards compatibility on which slick-pg relies is a tiny subset of the functionality that play-json provides. So, I can see some reason for relaxing the constraint.

Passion dampening withstanding, I think the separate modules for Scala libraries is the better approach:

  • In the case of a backwards compatibility issue, it's easier to release one of the modules with a concurrent binding during a transition. e.g. slick-pg-play-json-2.3 and slick-pg-play-json (compiled against latest).
  • (repeated) Separate modules declare their dependencies so that potential conflicts can be identified at compile time.
  • It's not very difficult to include in multiple libraries. I did it with op-rabbit, and I tend to favor the approach.

The most important argument, I think, is that separate modules, while increasing the amount signal in our build.sbt files, reduces the ambiguity. "provided" feels like something the Java folks would use, because chaining yourself to backwards compatibility is the Java way. In Scala, we break stuff.

What are your thoughts? What arguments persuaded you to combine them together?

@tminglei
Copy link
Owner

I think it will simplify the usage, which is why I combined the plugins to the main jar.

Can we try optional? It's not well supported by sbt before, but I noticed slick is using it.

@timcharper
Copy link
Contributor Author

My understanding is that semantically, optional is a better fit.

http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

However, unfortunately, sbt does not warn you if your dependency conflicts with an optional dependency :( So, no help, here, either.

The referenced maven page does say this:

Optional dependencies are used when it's not really possible (for whatever reason) to split a project up into sub-modules. The idea is that some of the dependencies are only used for certain features in the project, and will not be needed if that feature isn't used. Ideally, such a feature would be split into a sub-module that depended on the core functionality project...this new subproject would have only non-optional dependencies, since you'd need them all if you decided to use the subproject's functionality.

So... ¯_(ツ)_/¯

Optional is probably better. It still doesn't collide, cause warnings, or anything. Both provided and optional dependencies show up in the produced pom. Here's a sample I threw together:

    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.7</version>
        </dependency>
        <dependency>
            <groupId>com.typesafe.play</groupId>
            <artifactId>play-json_2.11</artifactId>
            <version>2.4.2</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.typesafe</groupId>
            <artifactId>config</artifactId>
            <version>1.3.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

I have the following dependencies in another library:

name := "p2"

version := "0.1"

scalaVersion := "2.11.7"

libraryDependencies += "default" %% "p1" % "0.1"

libraryDependencies += "com.typesafe.play" %% "play-json" % "2.3.4"

And, dependency-tree looks like this:

[info] default:p2_2.11:0.1 [S]
[info]   +-com.typesafe.play:play-json_2.11:2.3.4 [S]
[info]   | +-com.fasterxml.jackson.core:jackson-annotations:2.3.2
[info]   | +-com.fasterxml.jackson.core:jackson-core:2.3.2
[info]   | +-com.fasterxml.jackson.core:jackson-databind:2.3.2
[info]   | | +-com.fasterxml.jackson.core:jackson-annotations:2.3.0 (evicted by: 2.3.2)
[info]   | | +-com.fasterxml.jackson.core:jackson-annotations:2.3.2
[info]   | | +-com.fasterxml.jackson.core:jackson-core:2.3.2
[info]   | |
[info]   | +-com.typesafe.play:play-datacommons_2.11:2.3.4 [S]
[info]   | +-com.typesafe.play:play-functional_2.11:2.3.4 [S]
[info]   | +-com.typesafe.play:play-iteratees_2.11:2.3.4 [S]
[info]   | | +-com.typesafe:config:1.2.1
[info]   | | +-org.scala-stm:scala-stm_2.11:0.7 [S]
[info]   | |
[info]   | +-joda-time:joda-time:2.3
[info]   | +-org.joda:joda-convert:1.6
[info]   | +-org.scala-lang:scala-reflect:2.11.1 [S]
[info]   |
[info]   +-default:p1_2.11:0.1 [S]

No warnings displayed, no hint of incompatibility.

@tminglei
Copy link
Owner

Yeah, it won't appear in the dependency-tree.

But with independent plugins, we need package and import many minor jars, and these plugins will also bind to some specified version of third party dependencies.

So I want to know others' response.

@timcharper
Copy link
Contributor Author

Okay, that's fair. It's probably okay as is. :) If you feel strongly about it being the way it is, I won't complain any more.

@tminglei
Copy link
Owner

Well, last time I changed it to provided too hurry. This time I want it to be more cautious! ;-)

@tminglei
Copy link
Owner

Hi @timcharper, the changes of splitting addons to independent projects are ready. :-)

@timcharper
Copy link
Contributor Author

Hurray!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants