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

Shipping Apps Confidently with Firebase

Shipping Apps Confidently with Firebase

Subhrajyoti Sen

November 06, 2021
Tweet

More Decks by Subhrajyoti Sen

Other Decks in Programming

Transcript

  1. Shipping Apps Con dently
    with Firebase
    KeepTruckin
    Subhrajyoti Sen DevFest Greece & Cyprus 2021
    November 2021

    View Slide

  2. Crashes

    View Slide

  3. Crashlytics

    View Slide

  4. Crashlytics
    • Automatic crash reporting

    View Slide

  5. Crashlytics


    Automatic crash reporting
    But no limited to crash reporting

    View Slide

  6. Recording Non-fatal exceptions

    View Slide

  7. Recording Non-fatal exceptions
    try {
    // some code can throw an exception
    } catch (e: Exception) {
    Log.d(TAG, e.localizedMessage)
    }

    View Slide

  8. Recording Non-fatal exceptions
    try {
    // some code can throw an exception
    } catch (e: Exception) {
    Log.d(TAG, e.localizedMessage)
    }

    View Slide

  9. Recording Non-fatal exceptions
    try {
    // some code can throw an exception
    } catch (e: Exception) {
    FirebaseCrashlytics.getInstance().recordException(e)
    }

    View Slide

  10. Recording Non-fatal exceptions
    private class CrashReportingTree : Timber.Tree() {
    }

    View Slide

  11. Recording Non-fatal exceptions
    private class CrashReportingTree : Timber.Tree() {
    override fun log(priority: Int,
    tag: String?,
    message: String,
    t: Throwable?) {
    }
    }

    View Slide

  12. Recording Non-fatal exceptions
    private class CrashReportingTree : Timber.Tree() {
    override fun log(priority: Int,
    tag: String?,
    message: String,
    t: Throwable?) {
    if (priority == Log.ERROR && t != null) {
    FirebaseCrashlytics.getInstance().recordException(t)
    }
    }
    }

    View Slide

  13. Recording Non-fatal exceptions
    class MainApplication : Application() {
    override fun onCreate() {
    super.onCreate()
    Timber.plant(CrashReportingTree())
    }
    }

    View Slide

  14. Recording Non-fatal exceptions
    try {
    // some code can throw an exception
    } catch (e: Exception) {
    FirebaseCrashlytics.getInstance().recordException(e)
    }

    View Slide

  15. Recording Non-fatal exceptions
    try {
    // some code can throw an exception
    } catch (e: Exception) {
    Timber.e(e)
    }

    View Slide

  16. Understanding Crashes Better

    View Slide

  17. Analytics

    View Slide

  18. Analytics
    • We normally use analytics in isolation from crash
    reporting

    View Slide

  19. Analytics


    We normally use analytics in isolation from crash
    reporting
    Usually PMs check the analytics and Devs check the
    crashes

    View Slide

  20. Analytics



    We normally use analytics in isolation from crash
    reporting
    Usually PMs check the analytics and Devs check the
    crashes
    What if you can combine them to get a full view?

    View Slide

  21. Analytics

    View Slide

  22. Analytics

    View Slide

  23. Analytics
    binding.zoomImage.setOnClickListener {
    MixpanelAPI.track("Zoom button clicked")
    }

    View Slide

  24. Analytics
    binding.zoomImage.setOnClickListener {
    MixpanelAPI.track("Zoom button clicked")
    FirebaseAnalytics.getInstance(context)
    .logEvent("Zoom button clicked", mapOf("page", "map"))
    }

    View Slide

  25. Analytics
    interface AnalyticsProvider {
    fun track(
    analyticEvent: String,
    properties: Map? = null
    )
    }

    View Slide

  26. Analytics
    class FirebaseAnalyticsProvider(
    private val rebaseAnalytics: FirebaseAnalytics
    ): AnalyticsProvider {
    override fun track(analyticEvent: String, properties: Map?) {
    rebaseAnalytics.logEvent(analyticEvent, properties)
    }
    }

    View Slide

  27. Analytics
    class FirebaseAnalyticsProvider(
    private val rebaseAnalytics: FirebaseAnalytics
    ): AnalyticsProvider {
    override fun track(analyticEvent: String, properties: Map?) {
    rebaseAnalytics.logEvent(analyticEvent, properties)
    }
    }

    View Slide

  28. Analytics
    class AnalyticsManager {
    private val analyticsProviders = mutableListOf()
    fun addProvider(provider: AnalyticsProvider) {
    analyticsProviders.add(provider)
    }
    }

    View Slide

  29. Analytics
    class AnalyticsManager {
    //...
    fun track(analyticEvent: String, properties: Map?) {
    analyticsProviders.forEach { provider ->
    provider.track(analyticEvent, properties)
    }
    }
    }

    View Slide

  30. Analytics
    binding.zoomImage.setOnClickListener {
    analyticsManager.logEvent(
    "Zoom button clicked",
    mapOf("page", "map")
    )
    }

    View Slide

  31. Feature Flags

    View Slide

  32. What's a feature ag?

    View Slide

  33. What's a feature ag?
    if (isNewFeatureEnabled) {
    // allow access to shiny new feature
    } else {
    // prevent access to shiny new feature
    }

    View Slide

  34. Use cases

    View Slide

  35. Use cases
    • A/B Testing

    View Slide

  36. Use cases


    A/B Testing
    Rolling out new features

    View Slide

  37. Use cases



    A/B Testing
    Rolling out new features
    Rolling out rewrite of existing features

    View Slide

  38. Use cases




    A/B Testing
    Rolling out new features
    Rolling out rewrite of existing features
    Merge Work-in-progress features

    View Slide

  39. Types of Feature Flags?

    View Slide

  40. Types of Feature Flags?
    • Static

    View Slide

  41. Types of Feature Flags?


    Static
    Decided at build time

    View Slide

  42. Types of Feature Flags?



    Static
    Decided at build time
    Based on things like versionCode, buildVariant, etc

    View Slide

  43. Types of Feature Flags?




    Static
    Decided at build time
    Based on things like versionCode, buildVariant, etc
    Dynamic

    View Slide

  44. Types of Feature Flags?





    Static
    Decided at build time
    Based on things like versionCode, buildVariant, etc
    Dynamic
    Can be controlled at runtime either locally using dev
    settings

    View Slide

  45. Types of Feature Flags?






    Static
    Decided at build time
    Based on things like versionCode, buildVariant, etc
    Dynamic
    Can be controlled at runtime either locally using dev
    settings
    Or remotely via services like Firebase Remote Con g

    View Slide

  46. View Slide

  47. Show me code!!

    View Slide

  48. interface Con g {
    val key: String
    val default: Boolean
    val description: String
    }

    View Slide

  49. enum class FeatureFlags(
    override val key: String,
    override val default: Boolean,
    override val description: String
    ): Con g

    View Slide

  50. enum class FeatureFlags(
    override val key: String,
    override val default: Boolean,
    override val description: String
    ): Con g {
    NEW_CHECKOUT_FLOW(
    "checkout_ ow_v2",
    true,
    "Enable checkout ow V2 for trending items"
    )
    }

    View Slide

  51. interface FeatureFlagProvider {
    fun getValue(featureFlag: FeatureFlag): Boolean
    }

    View Slide

  52. class FirebaseFeatureFlagProvider: FeatureFlagProvider {
    private val remoteCon g =
    FirebaseRemoteCon g.getInstance()
    override fun getValue(featureFlag: FeatureFlag): Boolean {
    return remoteCon g.getBoolean(featureFlag.key)
    }
    }

    View Slide

  53. class RemoteCon gManager(
    private val featureFlagProvider: FeatureFlagProvider
    ) {
    fun isFeatureEnabled(featureFlag: FeatureFlag) =
    featureFlagProvider.getValue(featureFlag)
    }

    View Slide

  54. if (remoteCon gManager.isFeatureEnabled(NEW_CHECKOUT_FLOW)) {
    // allow access to shiny new feature
    } else {
    // prevent access to shiny new feature
    }

    View Slide

  55. Using Feature Flags effectively

    View Slide

  56. Using Feature Flags effectively
    • De ne success metrics

    View Slide

  57. Using Feature Flags effectively


    De ne success metrics
    Less Crashes?

    View Slide

  58. Using Feature Flags effectively



    De ne success metrics
    Less Crashes?
    Smoother experience?

    View Slide

  59. Using Feature Flags effectively




    De ne success metrics
    Less Crashes?
    Smoother experience?
    Implement using your Analytics library (like Mixpanel)

    View Slide

  60. Using Feature Flags effectively





    De ne success metrics
    Less Crashes?
    Smoother experience?
    Implement using your Analytics library (like Mixpanel)
    Create dashboards to compare

    View Slide

  61. @iamsubhrajyoti
    https://calendly.com/subhrajyotisen

    View Slide

  62. Credits: UC Davis

    View Slide