Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sorting and Reporting Your Dependencies with Gr...

Sorting and Reporting Your Dependencies with Gradle

All apps have dependencies, but what is the best way to manage and keep on top of them? This session takes a look at some simple steps, tools, and tricks to use Gradle to help us make dependency management far easier.

Starting with simple Gradle language features, we will also explore how to handle dependencies within more complex projects, dive into some useful Gradle plugins, and finally look into what the future of dependency management within Android may be.

This talk was part of Android Worldwide, July 27 2021

Ed Holloway-George

July 27, 2021
Tweet

More Decks by Ed Holloway-George

Other Decks in Technology

Transcript

  1. @Sp4ghettiCode • Ed George • Dad to a Pomeranian 🐶

    • Senior Android Dev @ ASOS Find me on social: • @Sp4ghettiCode 🍝 • ed-george.github.io Who am I?
  2. @Sp4ghettiCode What this talk is/isn’t! • IS a dive into

    ‘better’ dependency management with Gradle • IS a look into exciting new/upcoming Gradle features • IS my first ever talk 😅🎉 • IS NOT a ‘comprehensive guide’ on Gradle or Kotlin DSL • IS NOT showcasing the only ways to sort / report your dependencies
  3. @Sp4ghettiCode What will we learn! The Basics • What a

    dependency is • How we can define them within Gradle
  4. @Sp4ghettiCode What will we learn! Sorting • How to help

    manage your dependencies when scaling • What the future looks like 🔮
  5. @Sp4ghettiCode What will we learn! Reporting • How to keep

    on top of our dependencies • How to help report your dependencies to others
  6. @Sp4ghettiCode What is a dependency? dependencies { implementation project(“:my-module”) implementation

    files(‘folder/myDependency.jar’) implementation fileTree(dir: 'libs', include: [‘*.jar']) }
  7. @Sp4ghettiCode The common problems we face • Versioning inconsistencies •

    Non-centralised dependencies • Moving to a modular codebase • Out-of-date dependencies (and the ones I hope to help you fix)
  8. @Sp4ghettiCode The common problems we face • Versioning inconsistencies •

    Non-centralised dependencies • Moving to a modular codebase • Out-of-date dependencies (and the ones I hope to help you fix)
  9. @Sp4ghettiCode The humble extra properties block ext { libVersion =

    ‘1.2.3’ } dependencies { implementation “com.example:foo:$libVersion” implementation “com.example:bar:$libVersion” implementation “com.example:baz:$libVersion” implementation “com.example:etc:$libVersion” }
  10. @Sp4ghettiCode The humble extra properties block ext { libVersion =

    ‘1.2.3’ } dependencies { implementation “com.example:foo:$libVersion” implementation “com.example:bar:$libVersion” implementation “com.example:baz:$libVersion” implementation “com.example:etc:$libVersion” }
  11. @Sp4ghettiCode The humble extra properties block ext { libVersion =

    ‘1.2.3’ } dependencies { implementation “com.example:foo:$libVersion” implementation “com.example:bar:$libVersion” implementation “com.example:baz:$libVersion” implementation “com.example:etc:$libVersion” }
  12. @Sp4ghettiCode Bill of Materials dependencies { implementation platform('com.google.firebase:firebase-bom:28.3.0') No more

    need for explicit versions! implementation 'com.google.firebase:firebase-auth' implementation 'com.google.firebase:firebase-firestore' }
  13. @Sp4ghettiCode Bill of Materials BOMs readily available for: • Firebase

    • Kotlin • OkHTTP • Jackson • JUnit 5 • Not much else for Android (yet) 😢
  14. @Sp4ghettiCode The common problems we face • Versioning inconsistencies •

    Non-centralised dependencies • Moving to a modular codebase • Out-of-date dependencies (and the ones I hope to help you fix)
  15. @Sp4ghettiCode Creating a versions.gradle Part 1 def androidx_version = [:]

    androidx_version.appcompat = '1.0.2' versions.androidx = androidx_version def androidx_deps = [:] androidx_deps.appcompat = "androidx.appcompat:appcompat:$versions.androidx.appcompat" dependencies.androidx = androidx_deps … ext.deps = dependencies ext.versions = versions
  16. @Sp4ghettiCode Creating a versions.gradle Part 1 apply from: "$rootProject.rootDir/versions.gradle" dependencies

    { implementation deps.androidx.appcompat implementation deps.androidx.ktx_core … } app/build.gradle
  17. @Sp4ghettiCode Creating a versions.gradle Part 2 def Group(Closure closure) {

    closure.delegate = dependencies return closure } delegate refers to a third-party object where methods calls & properties are resolved versions.gradle
  18. @Sp4ghettiCode Creating a versions.gradle Part 2 ext { androidx =

    Group { // Previously defined deps implementation deps.androidx.appcompat implementation deps.androidx.ktx_core implementation deps.androidx.ktx_fragment … } … } versions.gradle
  19. @Sp4ghettiCode Creating a versions.gradle Part 2 ext { androidx =

    Group { implementation deps.androidx.appcompat … } kotlin = Group { implementation deps.kotlin.core … } … } dependencies { androidx() kotlin() … } versions.gradle app/build.gradle
  20. @Sp4ghettiCode Version Catalogs 🆕 Available from Gradle 7.0+ (April 2021)

    • Provides centralised dependency configuration • Generates type-safe accessors • Requires VERSION_CATALOGS feature preview to be enabled
  21. @Sp4ghettiCode Version Catalogs - Gradle dependencyResolutionManagement { versionCatalogs { libs

    { version('okHttp', ‘4.9.1’) alias(‘okhttp-core’).to(‘com.squareup.okhttp3’, ‘okhttp').versionRef('okHttp') } } } settings.gradle app/build.gradle dependencies { implementation libs.okhttp.core }
  22. @Sp4ghettiCode Version Catalogs - TOML [versions] okhttp = “4.9.1” [libraries]

    okhttp-core = { module = “com.squareup.okhttp3:okhttp”, version.ref = "okhttp" } gradle/libs.versions.toml app/build.gradle dependencies { implementation libs.okhttp.core }
  23. @Sp4ghettiCode Version Catalogs - Bundles [versions] okhttp = “4.9.1” [libraries]

    okhttp-core = { module = “com.squareup.okhttp3:okhttp”, version.ref = "okhttp" } okhttp-ws = { module = “com.squareup.okhttp3:okhttp-ws“, version.ref = “okhttp" } [bundles] okhttp = ["okhttp-core", “okhttp-ws"] gradle/libs.versions.toml app/build.gradle dependencies { implementation libs.bundles.okhttp }
  24. @Sp4ghettiCode The common problems we face • Versioning inconsistencies •

    Non-centralised dependencies • Moving to a modular codebase • Out-of-date dependencies (and the ones I hope to help you fix)
  25. @Sp4ghettiCode - A Project Manager “I need you to present

    the app’s outdated dependencies and their latest version available”
  26. @Sp4ghettiCode Basic Reporting ./gradlew :module:dependencies • Outputs the dependencies used

    for all configurations • Shows dependency versions • Tree view
  27. @Sp4ghettiCode Basic Reporting debugAndroidTestCompileClasspath +--- androidx.test.ext:junit:1.1.2 | +--- junit:junit:4.12 |

    | \--- org.hamcrest:hamcrest-core:1.3 | +--- androidx.test:core:1.3.0 | | +--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | | +--- androidx.test:monitor:1.3.0 | | | \--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | | \--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.3.1 | | \--- androidx.annotation:annotation:1.1.0 -> 1.2.0 | +--- androidx.test:monitor:1.3.0 (*) | \--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | … ./gradlew :module:dependencies
  28. @Sp4ghettiCode Basic Reporting debugAndroidTestCompileClasspath +--- androidx.test.ext:junit:1.1.2 | +--- junit:junit:4.12 |

    | \--- org.hamcrest:hamcrest-core:1.3 | +--- androidx.test:core:1.3.0 | | +--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | | +--- androidx.test:monitor:1.3.0 | | | \--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | | \--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.3.1 | | \--- androidx.annotation:annotation:1.1.0 -> 1.2.0 | +--- androidx.test:monitor:1.3.0 (*) | \--- androidx.annotation:annotation:1.0.0 -> 1.2.0 | … ./gradlew :module:dependencies
  29. @Sp4ghettiCode Dependency Insight Report ./gradlew :module:dependencyInsight --configuration myConf --dependency myDep

    • Gives further diagnostics on how a dependency is used • Shows dependency version constraints • Requires configuration and dependency flags
  30. @Sp4ghettiCode Gradle Version Plugin github.com/ben-manes/gradle-versions-plugin • Generates a Gradle task

    ‘dependencyUpdates’ • Displays a report of the project dependencies that are up-to-date / out-of-date • ‘Default’ reports in HTML, XML and JSON • Allows for custom reporting 👀
  31. @Sp4ghettiCode Example Output The following dependencies have later milestone versions:

    - androidx.appcompat:appcompat [1.0.2 -> 1.3.0-alpha01] https://developer.android.com/jetpack/androidx - androidx.core:core-ktx [1.0.2 -> 1.5.0-alpha01] https://developer.android.com/jetpack/androidx [...] 
 ./gradlew dependencyUpdates
  32. @Sp4ghettiCode (With Groovy’s HTML Builder) • DSL Style • Can

    be used to generate custom HTML page to report dependencies • Beginner Friendly! Custom Reporting
  33. @Sp4ghettiCode The common problems we face • Versioning inconsistencies •

    Non-centralised dependencies • Moving to a modular codebase • Out-of-date dependencies (and the ones I hope to help you fix)
  34. @Sp4ghettiCode TL;DR • When possible, centralise + generalise your dependencies

    • Consider Version Catalogs in future • Use dependency insight tasks for more info • Reporting can be made easier using Gradle Version Plugin
  35. @Sp4ghettiCode Thanks for watching! • Find me on Twitter @Sp4ghettiCode

    • More resources and links at ed-george.github.io/talks • Please do reach out if you have any cool ways of managing dependencies • Questions and Answers to follow…