在170期的adroid weekly里面有一篇文章,
说的是关于我们在gradle里面使用动态依赖这件事。
1. Dependencies can unexpectedly introduce behavior changes to your app. Read your changelogs carefully!
2. The same source built on two different machines can differ. How many times have you said "but it works on my machine?"
3. Similarly,builds built on thesamemachine but atdifferenttimes can differ. I've wasted so much time on builds that worked on minute then broke the next.4. Past builds cannot be reproduced perfectly. This makes it difficult to revert safely.
5. There aresecurity implicationsif a bad actor introduces a malicIoUs version of a dependenc
Don't use dynamic versions for your dependencies
Everyone,please,to stop using dynamic versions for your dependencies.
In Gradle,dynamic versions use the+
sign like so:
compile 'com.android.support:appcompat-v7:23.0.+'
Ideally,your builds should be predictable and consistent. Identical source code should yield the same result,every time you build.
Dynamic versions add nondeterminism to your build.In other words,the same source codemay notyield the same output. This behavior manifests itself in all sorts of nasty problems:
-
Dependencies can unexpectedly introduce behavior changes to your app. Read your changelogs carefully!
-
The same source built on two different machines can differ. How many times have you said "but it works on my machine?"
-
Similarly,builds built on thesamemachine but atdifferenttimes can differ. I've wasted so much time on builds that worked on minute then broke the next.
-
Past builds cannot be reproduced perfectly. This makes it difficult to revert safely.
-
There aresecurity implicationsif a bad actor introduces a malicIoUs version of a dependency.
The solution is simple:always specify your dependency versions explicitly.
But But But...!
Here's a couple of arguments I've heard for using dynamic versioning and why I disagree.
I don't want to bother updating dependencies.
Your laziness will likely cost you more time down the road fixing some problem created by dynamic versions.
Bugfix updates should be safe and absorbed as quickly as possible.
In other words,if you're using23.0.+
,it should never break because the patch version should only update for bug fixes.
There are two problems with this idea. First,you have to trust that the library is using versions to denote patches correctly. And second,you have to trust that the developerneverwrites a bug into a patch version. Two big ifs; not worth the risk.
My library needs to use dynamic versioning; otherwise I have to release a new version of the library every time one of its dependencies updates.
This is wrong on two counts.
First,userscanupdate your library's dependencies without a new version of your library. They just need to define the dependency on their own:
// Depends on appcompat-v7:23.0.0 compile 'com.trello:rxlifecycle-components:0.3.0' // Even though rxlifecycle-components uses 23.0.0,// the build will ultimately use 23.0.1 as provided below compile 'com.android.support:appcompat-v7:23.0.1'
Second,if a dependency updates in a way thatbreaksyour library,then you need to manually update your library anyways!
In other words: it isn't needed and it won't save you effort.
Developers can't be trusted to update their dependencies.
Otherwise known asthe Fabric argumentfor why you should use+
with their plugin:
// The Fabric Gradle plugin uses an open ended version to // react quickly to Android tooling updates classpath 'io.fabric.tools:gradle:1.+'
The choice here is thus: you can either break your build after updating tools (which is an expected occasional outcome),or your build can randomly break when you unknowingly get a new version of Fabric.
I would rather take the route where I know what changed vs. the one where I have to hunt down the root problem.
Removing Dynamic Versions
Hopefully you're itching to get rid of all your dynamic versions. How do you do it?
For Android developers,there's a couple handy tools you can use. If you're using Android Studio then you can select a dynamic version and useALT
+ENTER
to pop up the quickfix dialog. From there select "Replace with specific version."
If you want to see all your dependencies at once then use the taskandroidDependencies
:
$ ./gradlew androidDependencies
If you're not building Android then you'll have to resort to thedependencies
task:
$ ./gradlew dependencies
Often times you'll need to specify the subproject you're targeting for this task. Supposing my app is inapp-dir/
,this is how you'd do it:
$ ./gradlew :app-dir:dependencies
These tasks showmostdependencies but they're missing the buildscript ones (i.e.,plugins like Fabric). As far as I know,there's no easy way to list these. You have to add your own task that prints it out for you:
// Add this to your build.gradle task buildscriptDependencies << { buildscript.configurations.classpath.each { println it } }
Then you can run this new script to get the buildscript versions:
$ ./gradlew buildscriptDependencies
Once you've purged your dynamic versions,I suggest usingthe gradle-versions-pluginon a regular basis to update your dependencies.
Exception
As with everything in programming,there are always exceptions. There'sa plugin from Netflixthat partially solves dynamic version problems. It allows you to define a range for a dependency but then alsolocksthat dependency in place afterwards. This doesn't save you from a dependency update randomly breaking your build but it does keep builds consistent.
Personally,updating dependencies by hand is simple enough and I like to read changelogs to make sure nothing is catching me off guard. I haven't tried this plugin as a result,but it could be appropriate if you have enough tests in place to protect you from dependencies breaking code.
Thanks tothe many people who proofread this article:Wojtek Kaliciński,Johan Nilsson,Ryan Harter,Sebastiano Poggi,andJake Wharton.
http://blog.danlew.net/2015/09/09/dont-use-dynamic-versions-for-your-dependencies/?utm_source=Android+Weekly&utm_campaign=98aaa2f697-Android_Weekly_170&utm_medium=email&utm_term=0_4eb677ad19-98aaa2f697-337880413
原文链接:https://www.f2er.com/javaschema/284450.html