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

Reusable Libraries

Reusable Libraries

How to make reusable code work on Android.

E86c7de302b490b7f2a67e54960510d0?s=128

Ryan Harter

April 10, 2015
Tweet

Transcript

  1. Reusable Libraries Ryan Harter @rharter +RyanHarter

  2. My Apps Fragment Shift

  3. My Apps Fragment Shift

  4. My Apps Fragment Shift

  5. Steps to make libraries work • Identify good candidates •

    Limit scope and requirements • Design a good API • Document and Communicate • Treat it like a client project
  6. Identify Good Candidates

  7. Identify Good Candidates

  8. Identify Good Candidates • It’s not a library if it’s

    only used once
  9. Identify Good Candidates • It’s not a library if it’s

    only used once • Don’t reinvent the wheel
  10. Identify Good Candidates • It’s not a library if it’s

    only used once • Don’t reinvent the wheel • Two Categories
  11. Identify Good Candidates • It’s not a library if it’s

    only used once • Don’t reinvent the wheel • Two Categories • Utility
  12. Identify Good Candidates • It’s not a library if it’s

    only used once • Don’t reinvent the wheel • Two Categories • Utility • UI
  13. Identify Good Candidates

  14. Identify Good Candidates • Google for libraries

  15. Identify Good Candidates • Google for libraries • Check Android

    Arsenal
  16. Identify Good Candidates • Google for libraries • Check Android

    Arsenal • Look at what other apps use
  17. Identify Good Candidates • Google for libraries • Check Android

    Arsenal • Look at what other apps use • Be Confident
  18. Identify Good Candidates • Google for libraries • Check Android

    Arsenal • Look at what other apps use • Be Confident • Count Stars
  19. Identify Good Candidates • Google for libraries • Check Android

    Arsenal • Look at what other apps use • Be Confident • Count Stars • Inspect Source
  20. Limit Scope and Requirements

  21. Limit Scope and Requirements

  22. Limit Scope and Requirements • Choose a single problem to

    solve
  23. Limit Scope and Requirements • Choose a single problem to

    solve • Picasso - Efficient image loading and caching
  24. Limit Scope and Requirements • Choose a single problem to

    solve • Picasso - Efficient image loading and caching • Retrofit - Easy REST API access
  25. Limit Scope and Requirements • Choose a single problem to

    solve • Picasso - Efficient image loading and caching • Retrofit - Easy REST API access • Avoid “Apache Syndrome”
  26. Limit Scope and Requirements • Choose a single problem to

    solve • Picasso - Efficient image loading and caching • Retrofit - Easy REST API access • Avoid “Apache Syndrome” • Every Apache library depends on every other Apache library
  27. Limit Scope and Requirements • Library mission statement • One

    sentence • What the library does
  28. Limit Scope and Requirements • Library mission statement • One

    sentence • What the library does “Allow the user to load an image from any source.”
  29. Design a Good API

  30. Design a Good API

  31. Design a Good API • Who is your user?

  32. Design a Good API • Who is your user? •

    If user needs to mess with code, it’s not a library
  33. Design a Good API • Who is your user? •

    If user needs to mess with code, it’s not a library • Design from the outside in
  34. Design a Good API • Who is your user? •

    If user needs to mess with code, it’s not a library • Design from the outside in • Package your library
  35. API Strategies - Utility Requirements: Persist filter state to support

    undo/redo. public class HistoryManager<T> { public T undo(); public T redo(); public void push(T state); public void clear(); }
  36. API Strategies - Superclass Fragment Shift

  37. API Strategies - Superclass public class BaseExportActivity extends Activity {

    /** * Returns a list of preferred packages which appear above the * divider with a slightly larger icon than the rest. * * @return the package ids of the preferred packages. */ protected List<String> getPreferredPackages() { return DEFAULT_PREFERRED_PACKAGES; } /** * @return the public folder name to save files to. */ protected File getSaveFolder() { return new File(getPublicPicturesDirectory(), "Pixite"); } /** * Allows the AppInfo to be updated for things like Refragment or * Refilter. Default implementation does nothing. * * @param info The app info to update. */ protected void updateAppInfo(AppInfo info) { } }
  38. API Strategies - Isolated Activity Fragment Shift

  39. API Strategies - Isolated Activity

  40. API Strategies - Isolated Activity Intent i = new Intent(getActivity(),

    InspirationActivity.class); i.putExtra(InspirationActivity.EXTRA_USER_ID, "1234567890"); i.putExtra(InspirationActivity.EXTRA_ACCESS_TOKEN, "super_secret_access_token"); i.putExtra(InspirationActivity.EXTRA_SKIP_TAG, "shiftpromo"); i.putExtra(InspirationActivity.EXTRA_USERNAME, "shift_by_pixite"); startActivity(i);
  41. API Strategies - Isolated Activity Intent i = new Intent(getActivity(),

    InspirationActivity.class); i.putExtra(InspirationActivity.EXTRA_USER_ID, "1234567890"); i.putExtra(InspirationActivity.EXTRA_ACCESS_TOKEN, "super_secret_access_token"); i.putExtra(InspirationActivity.EXTRA_SKIP_TAG, "shiftpromo"); i.putExtra(InspirationActivity.EXTRA_USERNAME, "shift_by_pixite"); startActivity(i); <style name="AppTheme" parent="Theme.AppCompat.NoActionBar"> ... <item name="inspirationActivityStyle">@style/InspirationActivityStyle</item> <item name="inspirationTextStyle">@style/TextAppearance.AppCompat.Inverse</item> <item name="inspirationFollowButtonStyle">@style/Widget.InspirationButton.Follow</item> <item name="inspirationMoreButtonStyle">@style/Widget.InspirationButton.More</item> <item name="inspirationRowStyle">@style/Widget.InspirationRow</item> <item name="inspirationRowTextStyle">@style/TextAppearance.InspirationRow</item> </style>
  42. API Strategies - Hybrid Intent i = new Intent(this, ImageChooserActivity.class);

    startActivityForResult(i, REQUEST_CHOOSE_PHOTO);
  43. Distribution • Open Source (jcenter, Maven Central) • Private Maven

    Repo • Git Repository
  44. Distribution - gradle-git-repo uploadArchives { repositories { mavenDeployer { repository(url:

    'git@github.com:rharter/maven-repo.git/releases') snapshotRepository(url: ‘git@github.com:rharter/maven-repo.git/snapshots') // standard pom settings } } } https://github.com/rharter/gradle-git-repo
  45. Document and Communicate

  46. Document and Communicate

  47. Document and Communicate • If a library is only used

    once, is it a library?
  48. Document and Communicate • If a library is only used

    once, is it a library? • Communicate outside of engineering
  49. Document and Communicate • If a library is only used

    once, is it a library? • Communicate outside of engineering • Sales needs to know what to sell
  50. Document and Communicate • If a library is only used

    once, is it a library? • Communicate outside of engineering • Sales needs to know what to sell • Design needs to know components and limitations
  51. Document and Communicate • If a library is only used

    once, is it a library? • Communicate outside of engineering • Sales needs to know what to sell • Design needs to know components and limitations • Javadoc for Engineering, Wiki for others
  52. Manage the Project

  53. Manage the Project

  54. Manage the Project • Treat internal libraries like a client

    project
  55. Manage the Project • Treat internal libraries like a client

    project • Dedicate resources
  56. Manage the Project • Treat internal libraries like a client

    project • Dedicate resources • Manage requests
  57. Manage the Project • Treat internal libraries like a client

    project • Dedicate resources • Manage requests • Define requirements
  58. Manage the Project • Treat internal libraries like a client

    project • Dedicate resources • Manage requests • Define requirements • Enforce versioned release cycle
  59. Reusable Libraries @rharter +RyanHarter http://ryanharter.com