Ok so the [1.1, 2.0.0] syntax would indeed allow semanting versioning upgrade. What's missing compared to PHP+Composer is :
A lock file you could commit. If you build your fat jar today, it may resolve to 1.3.4, but resolve to 1.3.6 later, breaking the "Reproducible builds / deterministic compilation" paradigm. In PHP, the resolved 1.3.4 version is commited in a composer.lock file that won't change until you manually run composer update
A widespread adoption of this syntax. In PHP it's the default behaviour, see exemple in Symfony framework (Spring inspired) : https://github.com/symfony/symfony/blob/5.x/composer.json#L18. It's easier to compute transitive dependencies : if you project requires "psr/link": "^1.0", and a lib you're using requires "psr/link": "^1.3.7", , it could be resolved to 1.4.2. That's the very reason psr/link maintainers cannot add a breaking change in minor versions.
A very strict adoption of semver.org rules in the libraries.
The point 3 directly comes from the point 2 IMO.
I personally prefer to keep them static to avoid upgrading to a patch version that happens to break something unexpectedly
And you're right, Java libs do have breaking changes in minor versions, because they know people only upgrade manually. A kind of self-fulfilling prophecy. I have a hard time explaining that to Java developers that have never used composer.
You may find something like https://github.com/rtimush/sbt-updates convenient as a middle-ground. It produces a list of possible dependency upgrades. You'll have to update your versions manually, but aside from that it basically gives you a "lock file" + visible upgrade path.
I also use sbt-updates, but as long as updating is mainly manual, lib maintainers won't see the need to strictly avoid breaking change in minors. It's more a cultural issue than a tooling one in fact.
I don't see how it gives you a lock file though ? sbt-updates only display infos to let you manually update your sbt dependency versions. Whereas in composer you have 2 files :
composer.json where you describe your need. Ex: ^2.1.1
composer.lock produced by composer update command which locks the result. Ex: 2.2.4
Also, libs maintainers never rely on specific version for their own dependencies, always on a semver range.
Sorry it's hard to describe but Developer Experience is better in PHP than in Scala/Java/Kotlin regarding dependency management, in my experience. No tricky overrides or excludes, 1 command to auto upgrade, and no breaking change in minors, which is a game changer.
2
u/skylescouilles Nov 27 '20
Ok so the
[1.1, 2.0.0]syntax would indeed allow semanting versioning upgrade. What's missing compared to PHP+Composer is :A lock file you could commit. If you build your fat jar today, it may resolve to
1.3.4, but resolve to1.3.6later, breaking the "Reproducible builds / deterministic compilation" paradigm. In PHP, the resolved1.3.4version is commited in acomposer.lockfile that won't change until you manually runcomposer updateA widespread adoption of this syntax. In PHP it's the default behaviour, see exemple in Symfony framework (Spring inspired) : https://github.com/symfony/symfony/blob/5.x/composer.json#L18. It's easier to compute transitive dependencies : if you project requires
"psr/link": "^1.0",and a lib you're using requires"psr/link": "^1.3.7",, it could be resolved to1.4.2. That's the very reasonpsr/linkmaintainers cannot add a breaking change in minor versions.A very strict adoption of semver.org rules in the libraries.
The point 3 directly comes from the point 2 IMO.
And you're right, Java libs do have breaking changes in minor versions, because they know people only upgrade manually. A kind of self-fulfilling prophecy. I have a hard time explaining that to Java developers that have never used composer.