Bohemian Wrapsody

Bohemian Wrapsody

In this talk, Dmytro Danylyk will explain why wrapping third-party library is best practice? Why should you actually care? What are the benefits for you and your team?

Original presentation available here: https://docs.google.com/presentation/d/1EAkTS7wCyzf5J4hvf4ARSDt9UGJVydWFVxpYLv2SzP8/edit?usp=sharing

56d515afd6a1001e8264df0d96c7a80e?s=128

Dmytro Danylyk

April 15, 2019
Tweet

Transcript

  1. Bohemian Wrapsody Dmytro Danylyk Atlassian

  2. “Wrapping third-party APIs is a best practice.” Robert C. Martin

  3. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  4. Glide.with(context) .load("https://...") .apply(RequestOptions() .placeholder(R.drawable.placeholder) .transform(CircleCrop())) library api

  5. Glide.with(context) .load("https://...") .apply(RequestOptions() .placeholder(R.drawable.placeholder) .transform(CircleCrop())) library api ImageLoader(context).load( model =

    ImageModel.URL("https://..."), placeholder = Placeholder.FromResource(R.drawable.placeholder), transformation = Transformation.Circular ) Your api
  6. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  7. main-module image-loader-module glide-library

  8. main-module image-loader-module glide-library Glide 4.9.0 Breaking changes Glide 4.8.0 Breaking

    changes Glide 4.7.0 Breaking changes Glide 4.6.0 Breaking changes Glide 4.5.0 Breaking changes Glide 4.4.0 Breaking changes Glide 4.3.0 Breaking changes
  9. main-module image-loader-module glide-library Glide 4.9.0 Breaking changes Glide 4.8.0 Breaking

    changes Glide 4.7.0 Breaking changes Glide 4.6.0 Breaking changes Glide 4.5.0 Breaking changes Glide 4.4.0 Breaking changes Glide 4.3.0 Breaking changes Resolve here
  10. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  11. main-module image-loader-module uil-library 2014

  12. main-module image-loader-module uil-library main-module image-loader-module glide-library 2014 2019

  13. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  14. ImageLoader(context).load( model = ImageModel.URL("https://..."), placeholder = Placeholder.Default, transformation = Transformation.Circular

    ) Default placeholder
  15. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  16. main-module image-loader-module glide-library * SVG support * authentication * transformations

  17. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  18. fun test() { val repository = UserRepository( analytics = mock(MyAnalytics::class)

    ) // test code omitted }
  19. Benefits - define the API of the wrapper - more

    flexible to changes - ease updates during breaking changes - experiment with new technologies - share common logic - predefined configuration - additional functionality - loosely coupled system - easier to test - reuse modules across apps
  20. jira-module confluence-module image-loader-module glide-library project 1 project 2

  21. When? - if you have multiple projects - if you

    work on a long-term project - if you use library as a temporary solution
  22. When? - if you have multiple projects - if you

    work on a long-term project - if you use library as a temporary solution
  23. When? - if you have multiple projects - if you

    work on a long-term project - if you use library as a temporary solution
  24. When? now later effort

  25. How? - class - package - module - speeds up

    builds (cache + parallel) - separate dependencies - prevents from accidental usage of internal code/resources
  26. How? - class - package - module - speeds up

    builds (cache + parallel) - separate dependencies - prevents from accidental usage of internal code/resources Prefer this
  27. Tips - don’t leave library references in wrapper API -

    make wrapper API as abstract as possible - wrap API which you use, incrementally - put proxy on UI libraries - document things which cannot be wrapped
  28. ImageLoader(context).load( model = GlideURL(url), placeholder = Placeholder.Default, transformation = Transformation.Circular

    ) Glide reference
  29. Tips - don’t leave library references in wrapper API -

    make wrapper API as abstract as possible - wrap API which you use, incrementally - put proxy on UI libraries - document things which cannot be wrapped
  30. val observable: Observable<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION) val publisher:

    Publisher<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION)
  31. val observable: Observable<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION) val publisher:

    Publisher<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION) io.reactivex
  32. val observable: Observable<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION) val publisher:

    Publisher<Result> = AndroidPermissions() .observe(permission = Permission.LOCATION) io.reactivex org.reactivestreams
  33. Tips - don’t leave library references in wrapper API -

    make wrapper API as abstract as possible - wrap API which you use, incrementally - put proxy on UI libraries - document things which cannot be wrapped
  34. Tips - don’t leave library references in wrapper API -

    make wrapper API as abstract as possible - wrap API which you use, incrementally - put proxy on UI components - document things which cannot be wrapped
  35. val indicatorView = findViewById<IndicatorView>(R.id.indicator) indicatorView.showIndicator(index = 1) val controller =

    IndicatorController(indicatorView) controller.showIndicator(index = 1) Direct usage Proxy
  36. Tips - don’t leave library references in wrapper API -

    make wrapper API as abstract as possible - wrap API which you use, incrementally - put proxy on UI libraries - document things which cannot be wrapped
  37. Library Candidates - logger - analytics - image loader -

    http client - android permissions - schedulers - etc.
  38. @dmytrodanylyk slides.com/dmytrodanylyk medium.com/@dmytrodanylyk S speakerdeck.com/dmytrodanylyk S