Pro Yearly is on sale from $80 to $50! »

How not to fuckup with building mobile SDK and make clients happy (DevFest Prague)

How not to fuckup with building mobile SDK and make clients happy (DevFest Prague)

Are you working on the client library? Or design a public API for the module that is going to be used by other team or department?

In this session, Vitality will share his experience and key learnings from building a mobile SDKs for last 4 years.

F456ed67b75e58e533d11b301f5f62b5?s=128

Vitaliy Zasadnyy

November 04, 2017
Tweet

Transcript

  1. @zasadnyy With building the mobile SDK How not to Fuck

    Up Vitaliy Zasadnyy Head of Mobile @ GetSocial
  2. @zasadnyy Integrated SDK. But it doesn’t work.

  3. Developer. GDG Lead. Public Speaker. @zasadnyy

  4. None
  5. None
  6. None
  7. @zasadnyy UNDERSTANDING “WHY?” BETTER DEVELOPER MAKES YOU A

  8. @zasadnyy My first library… Develop

  9. @zasadnyy

  10. @zasadnyy SDK Lifecycle Develop 1

  11. @zasadnyy SDK Lifecycle Develop 1 Integrate 2 Support 3 Update

    4
  12. Develop 1

  13. Integrate

  14. <receiver android:name="im.getsocial.InstallReferrerReceiver"> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER"/> </intent-filter> </receiver> <provider android:name="im.getsocial.sdk.invites.ImageContentProvider" <meta-data

    android:name="im.getsocial.sdk.AppId" android:value="LuDPp7W0J4"/> <activity android:name="com.demo.GetSocialDeepLinkingActivity"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="demo.gsc.im"/> <data android:scheme="getsocial" android:host="LuDPp7W0J4"/> </intent-filter> </activity> GetSocial.init()
  15. <receiver android:name="im.getsocial.InstallReferrerReceiver"> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER"/> </intent-filter> </receiver> <provider android:name="im.getsocial.sdk.invites.ImageContentProvider" <meta-data

    android:name="im.getsocial.sdk.AppId" android:value="LuDPp7W0J4"/> <activity android:name="com.demo.GetSocialDeepLinkingActivity"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="demo.gsc.im"/> <data android:scheme="getsocial" android:host="LuDPp7W0J4"/> </intent-filter> </activity>
  16. @zasadnyy Android manifest merging App manifest Lib 1 manifest Lib

    2 manifest Lib N manifest …
  17. @zasadnyy Gradle plugin apply plugin: 'im.getsocial'

  18. @zasadnyy Gradle plugin apply plugin: 'im.getsocial' getsocial { appId "LGa80P9790xsg4"

    }
  19. @zasadnyy Android Studio plugin

  20. @zasadnyy Android Studio plugin

  21. @zasadnyy Auto initialisation <provider android:name="im.getsocial.AutoInitContentProvider" android:authorities="..." android:exported="false" />

  22. @zasadnyy Boilerplate ➡ Copy/Paste ➡ Bugs Why?

  23. @zasadnyy IS BETTER LESS CODE

  24. @zasadnyy API SURPRISES AVOID

  25. @zasadnyy Avoid API surprises Thread.interrupted() Returns the current interrupted status

    and then clears it
  26. @zasadnyy Avoid API surprises

  27. @zasadnyy Avoid API surprises Thread.interrupted() Returns the current interrupted status

    and then clears it
  28. @zasadnyy Make API of your library as boring as possible

    - Chris Sells, Google
  29. @zasadnyy

  30. @zasadnyy INTERNALS HIDE

  31. @zasadnyy Hide internals

  32. @zasadnyy Hide internals Use .internal package Keep everything private by

    default Bonus: easy to generate Javadocs
  33. @zasadnyy There is much more!

  34. @zasadnyy ? Library is crashing your app?

  35. @zasadnyy

  36. @zasadnyy CRASH HOST APP NEVER

  37. @zasadnyy Prevent crashes Rx @Nullable / PMD / FindBugs /

    Lint Development Mode
  38. @zasadnyy Development mode if (BuildConfig.IS_DEVELOPMENT) { _executionPolicy = new StrictExecutionPolicy();

    }
  39. @zasadnyy Development mode if (BuildConfig.IS_DEVELOPMENT) { _executionPolicy = new StrictExecutionPolicy();

    } else { _executionPolicy = new SilentExecutionPolicy(); }
  40. @zasadnyy SUPPORT

  41. @zasadnyy Give a voice to your users GitHub issue tracker

    Intercom Support email …
  42. @zasadnyy Get ready to repetitive questions

  43. @zasadnyy DOCS

  44. @zasadnyy Documentation is like sex. Even bad is better than

    nothing
  45. @zasadnyy Key parts Step by step tutorials Product guides API

    Reference
  46. @zasadnyy

  47. @zasadnyy

  48. @zasadnyy

  49. @zasadnyy What is wrong with snippet? CurrentUser user = getSocial.getCurrentUser();

  50. @zasadnyy What is wrong with snippet? CurrentUser user = getSocial.getCurrentUser();

  51. @zasadnyy ALL SNIPPETS MUST COMPILE

  52. @zasadnyy Better snippet import im.getsocial.sdk.GetSocial; import im.getsocial.sdk.CurrentUser; ... CurrentUser user

    = GetSocial.getInstance().getCurrentUser();
  53. Google Developers Documentation Style Guide

  54. @zasadnyy Documentation engine GitHub Wiki Jekyll MkDocs …

  55. @zasadnyy ? Favourite source of copy / paste code?

  56. @zasadnyy

  57. @zasadnyy DEMOS

  58. @zasadnyy Demo apps Make demos well documented Keep SDK integration

    code separated
  59. Support

  60. @zasadnyy ? You’ve got support request. Now what?

  61. @zasadnyy Two types of problems Integration time problems End-user side

    problems
  62. @zasadnyy Easy way to collect DEBUG information

  63. @zasadnyy Debug SDK configuration adb shell setprop debug.getsocial.sdk.app com.demo

  64. @zasadnyy Actionable errors public class GetSocialException extends RuntimeException { private

    final int _errorCode; … }
  65. @zasadnyy Actionable errors public class GetSocialException extends RuntimeException { private

    final int _errorCode; … }
  66. @zasadnyy Solving end-user side problems Comprehensive logs Errors analytics

  67. @zasadnyy Solving end-user side problems void trackError(GetSocialException exception) { ...

    AnalyticsTrackManager.trackAnalyticsEvent( AnalyticsEventDetails.Name.SDK_ERROR, eventProperties); }
  68. @zasadnyy

  69. @zasadnyy

  70. @zasadnyy THINK ABOUT SUPPORT AHEAD

  71. Update

  72. @zasadnyy ? Just download and lean back?

  73. @zasadnyy Update. Build. And…

  74. @zasadnyy

  75. @zasadnyy UPDATES SMOOTH

  76. @zasadnyy Backward compatibility Use @Deprecation cycle /** * @deprecated use

    {@link #getAllIdentities()} instead. * Method will be removed in SDK v5.0.0. */ @Deprecated public List<String> getIdentities() { ... }
  77. @zasadnyy Semantic versioning v4.5.1 Major Minor Bugfix

  78. @zasadnyy Versioned packages import okhttp3; import im.getsocial.sdk6;

  79. @zasadnyy Versioned packages Partial transition A/B testing import okhttp3; import

    im.getsocial.sdk6;
  80. @zasadnyy Changelog Fixed issues New features Deprecations Upgrade guide

  81. @zasadnyy

  82. To sum up

  83. @zasadnyy PER APP 17 SDKs Source: Safe SDK

  84. @zasadnyy SDK Lifecycle Develop 1

  85. @zasadnyy SDK Lifecycle Develop Integrate Support Update 1 2 3

    4
  86. @zasadnyy API can be you biggest asset of liability -

    Joshua Bloch Put yourself in your customer’s shoes - Cesare Rocchi
  87. @zasadnyy Happy dog Make clients happy again.

  88. @zasadnyy Find me at: @zasadnyy / zasadnyy.com Questions? Děkuji! Get

    the app at: devfestcz.gsc.im/1/getamos