7+1 tips about [Android] App Modularization | [Android] Architecture Night

7+1 tips about [Android] App Modularization | [Android] Architecture Night

Nowadays, App modularization is a technique largely adopted that gives lots of advantages. But how to approach it?
This talk will not focus on the pro and cons of modularization but instead on the approach and the process to achieve it. In particular, I want to share the approach that I followed to modularize an existing application and a new one. I want also to share the failures and all the struggles that came in my head while approaching the process.

9da5d5cc4b6a9f28058152e28364b02a?s=128

Marco Gomiero

February 04, 2020
Tweet

Transcript

  1. 2.

    ! What this talk is not about • 101 about

    modularization • Pro and cons [Android] Architecture Night - @marcoGomier
  2. 3.

    ! What this talk is about • 101 about modularization

    • Pro and cons • Approach and process • Failure and struggles [Android] Architecture Night - @marcoGomier
  3. 4.

    Marco Gomiero ! Mobile Engineer @ Uniwhere "# $ Co-Lead

    @ GDG Venezia ! Stalking info • Twitter: @marcoGomier • Github: prof18 • Website: marcogomiero.com [Android] Architecture Night - @marcoGomier
  4. 5.

    Uniwhere Uniwhere is an app that makes college less stressful

    by making university services smarter and more connected. • ! Started in 2015 as MVP • " Lots of iterations • # Time for [more] solid architecture [Android] Architecture Night - @marcoGomier
  5. 6.
  6. 9.

    Modularization in few words emojis • ! Simple development •

    "# Split responsibilities • $ Reusable modules Source: https://speakerdeck.com/beraldofilippo/the-clean-cut?slide=10
  7. 10.

    Modularization in few words emojis • ! Dynamic features modules

    • " Faster Builds • # Simple test automation Source: https://speakerdeck.com/beraldofilippo/the-clean-cut?slide=10
  8. 11.
  9. 14.

    Jeroen Mols's series about modularization 1. Modularization - Why you

    should care 2. Modularization - A successful architecture 3. Modularization - Real-life example 4. Modularization - How to approach 5. Modularization - Lessons learned https://jeroenmols.com/blog/
  10. 22.

    Monolithic Application └── app └── src └── main └── java

    └── com.prof18.myapplication ├── DashboardFragment.kt ├── HomeFragment.kt ├── MainActivity.kt ├── NotificationsFragment.kt ├── ProfileActivity.kt └── ProfileSettingsActivity.kt [Android] Architecture Night - @marcoGomier
  11. 23.
  12. 25.
  13. 26.
  14. 27.
  15. 28.

    Think a feature as a flow of screens [in the

    same context] [Android] Architecture Night - @marcoGomier
  16. 32.

    Library Modules • Android or Pure Kotlin library • Never

    depend on feature or app • A library can depend on another [Android] Architecture Night - @marcoGomier
  17. 33.

    Feature Modules • Android library • Never depend on other

    features or app • Depends on one or more libraries [Android] Architecture Night - @marcoGomier
  18. 34.

    App Module • Android application • Link all the modules

    together • Depends on other features and library [Android] Architecture Night - @marcoGomier
  19. 35.

    Monolithic Application └── app └── src └── main └── java

    └── com.prof18.myapplication ├── DashboardFragment.kt ├── HomeFragment.kt ├── MainActivity.kt ├── NotificationsFragment.kt ├── ProfileActivity.kt └── ProfileSettingsActivity.kt [Android] Architecture Night - @marcoGomier
  20. 36.

    Modularized App [1] ├── app │ └── src │ └──

    main │ └── java │ └── com.prof18.myapplication │ └── MainActivity.kt │ [Android] Architecture Night - @marcoGomier
  21. 37.

    Modularized App [2] └── features ├── home │ └── src

    │ └── main │ └── java │ └── com.prof18.myapplication.features.home │ ├── DashboardFragment.kt │ ├── HomeActivity.kt │ ├── HomeFragment.kt │ └── NotificationsFragment.kt └── profile └── src └── main └── java └── com.prof18.myapplication.features.profile ├── ProfileActivity.kt └── ProfileSettingsActivity.kt [Android] Architecture Night - @marcoGomier
  22. 39.

    How about navigation? • Within a feature -> "Classic way",

    e.g. explicit intent, navigation component • Between features -> Implicit intent [Android] Architecture Night - @marcoGomier
  23. 40.

    Between features navigation Declare the implicit intent in the Manifest

    <activity android:name="com.prof18.filmatic.features.home.ui.HomeActivity" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="com.prof18.filmatic.features.home" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> [Android] Architecture Night - @marcoGomier
  24. 41.

    Between features navigation Create an object to help you with

    the boilerplate object Actions { fun openHomeIntent(context: Context): Intent = internalIntent(context, "com.prof18.filmatic.features.home") private fun internalIntent(context: Context, action: String) = Intent(action).setPackage(context.packageName) } [Android] Architecture Night - @marcoGomier
  25. 43.

    Pull Code Up • Treat the old code "as a

    library" and then create new modules • A gentle process [Android] Architecture Night - @marcoGomier
  26. 44.

    Pull Code Down • Hold the app together and then

    extract new modules • A more aggressive process [Android] Architecture Night - @marcoGomier
  27. 45.
  28. 46.

    Pull Code Up 1. Create new module core 2. All

    existing code into core 3. New app module that decides what to open 4. Extract a new feature from core 5. … [Android] Architecture Night - @marcoGomier
  29. 47.
  30. 49.
  31. 50.

    Change of strategy: Pull Code Down 1. Maintain all the

    code in the existent app module 2. Move [some] common code to the core module 3. Start creating new features and libraries [Android] Architecture Night - @marcoGomier
  32. 52.

    Fail as fast as you can • It's ok to

    fail during this process • Keep pushing • Allocate a big initial push to get things started [Android] Architecture Night - @marcoGomier
  33. 54.
  34. 55.

    String resources • Each module has its strings • Common

    strings on core module • ! for separation of concerns • " to maintain with a "translation platform" [Android] Architecture Night - @marcoGomier
  35. 56.

    String resources • Each module has its strings • Common

    strings on core module • All strings on core module [Android] Architecture Night - @marcoGomier
  36. 59.
  37. 62.

    How to approach a no Dagger project? • Start gently

    with some [common] dependencies • Continue with more dependencies [Android] Architecture Night - @marcoGomier
  38. 64.

    Modules configuration We need a smart way to handle dependencies

    and configurations across all modules [Android] Architecture Night - @marcoGomier
  39. 65.

    SDK Configuration subprojects { afterEvaluate { project -> if (project.hasProperty('android'))

    { android { buildToolsVersion Config.buildTools compileSdkVersion Config.compileSdk defaultConfig { minSdkVersion Config.minSdk targetSdkVersion Config.targetSdk testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } compileOptions { sourceCompatibility Config.javaVersion targetCompatibility Config.javaVersion } } } } } [Android] Architecture Night - @marcoGomier
  40. 66.

    SDK Configuration object Config { val minSdk = 21 val

    compileSdk = 29 val targetSdk = 29 val javaVersion = JavaVersion.VERSION_1_8 val buildTools = "29.0.0" } [Android] Architecture Night - @marcoGomier
  41. 67.

    Dependency Management object Versions { val appcompat = "1.0.2" val

    design = "1.0.0" val cardview = "1.0.0" ... } object Deps { val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}" val design = "com.google.android.material:material:${Versions.design}" val cardview = "androidx.cardview:cardview:${Versions.cardview}" ... } [Android] Architecture Night - @marcoGomier
  42. 69.

    Common dependencies: dependencies { implementation Deps.appcompat implementation Deps.constraintLayout implementation Deps.design

    implementation Deps.vectorDrawable implementation Deps.timber } apply from: '../../shared_dependencies.gradle' [Android] Architecture Night - @marcoGomier
  43. 71.

    Dependencies Update ./gradlew dependencyUpdates ------------------------------------------------------------ : Project Dependency Updates (report

    to plain text file) ------------------------------------------------------------ The following dependencies are using the latest milestone version: - androidx.cardview:cardview:1.0.0 - androidx.constraintlayout:constraintlayout:2.0.0-beta3 - androidx.emoji:emoji-bundled:1.0.0 .... The following dependencies have later milestone versions: - androidx.appcompat:appcompat [1.1.0 -> 1.2.0-alpha01] https://developer.android.com/jetpack/androidx - androidx.browser:browser [1.0.0 -> 1.2.0-rc01] https://developer.android.com/jetpack/androidx - androidx.core:core-ktx [1.0.1 -> 1.2.0-rc01] [Android] Architecture Night - @marcoGomier
  44. 73.

    What approach to follow? A big sprint? Small chunks of

    work? [Android] Architecture Night - @marcoGomier
  45. 74.

    My approach • Start with preliminaries • move common code/resources

    to a [or many] core module[s] • Setup the navigation between features • … • Start by modularizing a single feature [Android] Architecture Night - @marcoGomier
  46. 75.

    My approach • Ship that feature [after testing, QA, etc.

    ] • Start modularizing more features [Android] Architecture Night - @marcoGomier
  47. 79.

    Conclusions • Plan a big initial push to get things

    started • It's a long [and difficult] journey but it totally worth it • Don't be afraid to fail [Android] Architecture Night - @marcoGomier
  48. 80.
  49. 82.