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

Productive Mobile Development for Engineers

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Productive Mobile Development for Engineers

Tips and Tricks for Productive Mobile Development. Given in Droidcon Egypt on October 21st, 2022.

Avatar for Ahmed El-Helw

Ahmed El-Helw

October 21, 2022
Tweet

More Decks by Ahmed El-Helw

Other Decks in Programming

Transcript

  1. Factors affecting Speed Things to Consider • Distractions • Communication

    Problems • Con fl icting Priorities • Technical Debt
  2. Factors affecting Speed Things to Consider • Distractions • Communication

    Problems • Con fl icting Priorities • Technical Debt • Production Fires
  3. Factors affecting Speed Things to Consider • Distractions • Communication

    Problems • Con fl icting Priorities • Technical Debt • Production Fires • Hardware
  4. Process Bottlenecks Mobile Bottlenecks • Company release process • Application

    store review process • Application store rejections • Adoptions take time
  5. Customer Behavior Understanding and Monitoring Customer Behavior • Dashboards •

    critical business statistics • conversion funnels • Slice by application version • Alerts
  6. Dealing with Problems How to React to Problems • Ignore

    it for now • Hot Fix in Production • Release takes time • Adoption takes time • Risky
  7. Other Considerations Things to Keep in Mind • Be mindful

    about: • The e ff ect of experiments on each other • The e ff ect of feature fl ags on each other • Dead Experiments increase Technical Debt • Can tooling help here?
  8. Data Some odds and ends about Data • Building trust

    with Customers • Compliance • App Stores • Governments
  9. Modularization Structuring Code • Have a set of rules and

    guidelines • Split APIs and Implementation
  10. Modularization Structuring Code / / in profile-api module interface Profile

    { fun isLoggedIn(): Boolean fun currentCustomer(): Customer? fun editCustomerIntent(context: Context): Intent? }
  11. Modularization Structuring Code / / in profile module class ProfileImpl

    constructor( private val profileRepository: ProfileRepository ) : Profile { override fun isLoggedIn(): Boolean = currentCustomer() != null override fun currentCustomer(): Customer? { return profileRepository.provideCustomer() } override fun editCustomerIntent(context: Context): Intent { return Intent(context, EditProfileActivity : : class.java) } }
  12. Modularization Structuring Code / / in profile-noop module class ProfileNoop

    : Profile { override fun isLoggedIn(): Boolean = true override fun currentCustomer(): Customer = Customer(123L, "Test") override fun editCustomerIntent(context: Context) = null }
  13. Modularization Structuring Code fun provideProfile(): Profile { return if (isDebug)

    { ProfileNoop() } else { ProfileImpl(ProfileRepository()) } }
  14. Benefits of Modularization Structuring Code • Better isolation of Features

    • Easier sharing • Easier and faster testing • Ability to stub implementations • Standalone apps
  15. Frameworks that Handle Everything Sharing Code Between Platforms • Pros

    • Potentially easier to hire for • Write once, use everywhere • Faster development (hot reload, etc) • Potential for hot loading code
  16. Frameworks that Handle Everything Sharing Code Between Platforms • Cons

    • Need to explicitly build separate UI for iOS and Android • Doesn’t “feel” native irrespective • New platform features are di ffi cult to adopt - need to wait • Overhead on binary size • Rejections Likely
  17. C/C++ Sharing Code Between Platforms • Cons • Di ffi

    cult • Still have to handle di ff erences between platforms • Custom development environment
  18. Kotlin Multiplatform Sharing Code Between Platforms • Pros • Completely

    native • Easy to learn for engineers writing Swift • Lots of third party libraries • Backed by JetBrains and Google • Supports a plethora of platforms
  19. Kotlin Multiplatform Sharing Code Between Platforms • Cons • iOS

    inter-op with Objective-C instead of Swift • Convincing iOS Engineers is Di ffi cult • Tooling • Still in the process of maturing
  20. Alternatives Sharing Between Platforms • Code generation • Annotation processors

    • Compiler plugins, Gradle plugins • Templating code generators (Stencil, …)
  21. Sharing Code Generating Code data class Car( val make :

    String, val model : String, val vin : String, val vendor : String, )
  22. Sharing Code Generating Code struct Car { let make: String

    let model: String let vin: String let vendor: String }
  23. Sharing Code Generating Code data class {{ component.name }}( {%

    for key, value in component.fields %} val {{ key | lowerFirstLetter }} : {{ value | upperFirstLetter }}, {% endfor %} )
  24. Sharing Code Generating Code struct {{ component.name }} { {%

    for key, value in component.fields %} let {{ key | lowerFirstLetter }}: {{ value | upperFirstLetter }} {% endfor %} }
  25. Things to Share Sharing Between Platforms • Analytics • Business

    Logic • Vocabulary • Architecture • Design System • Versioning • Release Process
  26. First Lines of Defense Catching Issues Early • The build

    process itself • Automated checkers • Lint • Code styling enforcers • Code smell detection • Coverage • Code Review helps catch issues early
  27. Tests Catching Issues Early • Tests • Unit Tests •

    Integration Tests • On-Device Integration Tests (“UI Tests”) • Screenshot Tests • Maestro Tests
  28. Dependency-Diff-Tldr Exposing Hidden Changes Upgraded Dependencies 
 com.squareup.moshi:moshi-adapters:1.14.0, (changed from

    1.13.0) 
 org.jetbrains.kotlin:kotlin-stdlib:1.7.20, (changed from 1.7.10) 
 org.jetbrains.kotlin:kotlin-stdlib-common:1.7.20, (changed from 1.7.10) 
 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.20, (changed from 1.7.10) 
 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20, (changed from 1.7.10)
  29. Diffuse Exposing Hidden Changes │ compressed │ uncompressed ├───────────┬───────────┬──────────┼───────────┬───────────┬────────── APK

    │ old │ new │ diff │ old │ new │ diff ──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼────────── dex │ 11.6 MiB │ 11.6 MiB │ -107 B │ 29.4 MiB │ 29.4 MiB │ -336 B arsc │ 1.8 MiB │ 1.8 MiB │ -992 B │ 1.8 MiB │ 1.8 MiB │ -988 B manifest │ 5.6 KiB │ 5.6 KiB │ +1 B │ 27.6 KiB │ 27.6 KiB │ 0 B res │ 1.1 MiB │ 1.1 MiB │ -3 KiB │ 1.3 MiB │ 1.3 MiB │ -4.8 KiB asset │ 404.2 KiB │ 404.2 KiB │ 0 B │ 678.6 KiB │ 678.6 KiB │ 0 B other │ 173.6 KiB │ 173.1 KiB │ -550 B │ 336.9 KiB │ 335.7 KiB │ -1.3 KiB ──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼────────── total │ 15.1 MiB │ 15.1 MiB │ -4.6 KiB │ 33.5 MiB │ 33.5 MiB │ -7.4 KiB
  30. Expose Hidden Changes Catching Issues Early • Transitive Dependencies •

    Binary Size • Binary compatibility breaking changes
  31. Binary Compatibility Validator Exposing Hidden Changes FAILURE: Build failed with

    an exception. * What went wrong: Execution failed for task ':miniapp:apiCheck'. > API check failed for project miniapp. --- /bitrise/src/miniapp/api/miniapp.api +++ /bitrise/src/miniapp/build/api/miniapp.api @@ -16,6 +16,7 @@ public abstract interface class com/careem/superapp/lib/miniapp/ IntegrationDependencies { public abstract fun provideEventBus ()Lcom/careem/ superapp/lib/eventbus/EventBus; + public abstract fun provideLocationPickerSdk ()Lcom/ careem/globalexp/locations/api/LocationPickerSdk; } You can run :miniapp:apiDump task to overwrite API declarations
  32. Expose Hidden Changes Catching Issues Early • Transitive Dependencies •

    Binary Size • Binary compatibility breaking changes • Permissions
  33. Expose Hidden Changes Tooling • di ff use • dependency-di

    ff -tldr / dependency-guard • metalava-gradle / binary-compatibility-validator
  34. Releases Catching Issues Early • Beta program • Staged rollouts

    to production • Release early, release often • Release should be a train, not a bus
  35. Dashboards and Data Catching Issues Early • Do not hide

    crashes • Handled exceptions and breadcrumbs are useful • Developer and performance metrics • Development Tooling • Chucker • LeakCanary
  36. Engineers are Humans Engineering Cultures • All humans make mistakes

    • Blame is bad • Blame is the enemy of ownership
  37. When Issues Arise Engineering Cultures • How could this have

    been prevented? • Why was this not caught earlier? • Combine fi xes with veri fi cation tests. • Post mortem