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

Successfully Publishing a Tested, Upgradeable and Documented Open Source Library

Successfully Publishing a Tested, Upgradeable and Documented Open Source Library

You’ve written some code, and you’d like to release it as Open Source. Congratulations!

Publishing an Open Source library goes beyond just releasing your code on Github. New users with different use cases means preparing for the unpredictable. How do you ensure your code is safe and efficient? Is your code easy to read? Do you have a plan for upgrades in the future?

This talk will look at best practices and showcase a checklist to follow when writing and publishing an Open Source Library, from the documentation to ensuring your library works as intended and doesn’t break applications using it.

Cf95f93e78f6d6dd0630049396f723c6?s=128

Xavier Gouchet

July 07, 2022
Tweet

More Decks by Xavier Gouchet

Other Decks in Programming

Transcript

  1. How to write a safe and reliable Open Source Library

  2. Xavier F. Gouchet Senior Software Engineer at Datadog @xgouchet /

    @datadoghq 2
  3. 3

  4. 0 Introduction 4

  5. github.com/DataDog/dd-sdk-android 5 commit 0db48d14dea27ac02e8ddeb9ccf7413feaacc20e Author: Xavier F. Gouchet Date: Mon

    Nov 4 13:38:30 2019 +0100 Initial drop with base gradle config
  6. Repository statistics - 2400+ commits - 3 developers - 20+

    contributors - (internal and community) - 30 published versions - 10 libraries 6
  7. 1 MAKING IT SAFE 7

  8. Reliability is key 8 ▪ Library lives in hundreds apps…

    ▪ … deployed on 100k+ devices
  9. Notice potential issues early 9 Compilation CI Code Review Dogfooding

    Production Cost of fixing a bug Time
  10. Ensure the code is safe 10 ▪ objective zero crash

    ▫ Static Analysis ▫ Code review ▫ *-tests ▪ Real life use cases
  11. Static analysis (Detekt) ▪ Forbid throwing exceptions ▪ Forbid specific

    Kotlin syntax ▫ check ▫ require ▫ !! ▪ List all third party methods throwing exceptions 11
  12. Mandatory Code Review ▪ Increase readability ▪ Generate discussion ▫

    Data structure ▫ Design Patterns ▫ Third party libraries 12
  13. “Testing is doubting!” 13

  14. Unit/Integration/End-to-end Testing ▪ Strict policy on the coverage ▪ Deal

    with flaky test ASAP ▪ Stay confident in our tests 14
  15. Real life use cases ▪ Dogfooding in our own apps

    ▪ Regular tests using OSS apps ▫ Wikipedia ▫ Reddit client ▫ HackerNews client 15
  16. Respect privacy 16 ▪ Leverage Sandbox storage / Cache ▪

    Add GDPR option ▪ Write doc about Data Collection
  17. 2 MAKING IT EFFICIENT 17

  18. Limit library performance impact 18 ▪ Offload heavy computation to

    background threads/workers ▪ Track Memory Leaks
  19. Monitor library overhead 19 ▪ Compute the impact of the

    library on ▫ CPU ▫ Memory ▫ Network ▫ …
  20. Keep a focus on performance 20 ▪ Track the performance

    impact for each update
  21. 3 MAKING IT USABLE 21

  22. Opt-in or opt-out by default 22 ▪ Balance between “it

    works out of the box” and “it doesn’t do anything that I don’t know of” ▪ Onboarding should work in 15 minutes
  23. Every thing can be configured ▪ Allow enabling/disabling individual features

    ▪ Allow tweaking sampling rates, thresholds, … 23
  24. Use sensible defaults 24 ▪ New customers don’t need to

    configure everything right now… ▪ … or ever
  25. Communicate ▪ Log any actionable “issue” ▫ configuration error ▫

    feature misuse ▫ key internal events ▪ Add actions or documentation links in the message ▪ Provide information about what the library is doing 25
  26. 4 MAKING IT FUTURE PROOF 26

  27. Keep track of API surface 27 ▪ Prevent any API

    breaking change ▪ Provide new option but keep the old ones working ▫ with @Deprecated ▫ with a LogCat log ▪ Provide migration guide
  28. Monitor dependencies 28 ▪ Review changelogs ▪ Be mindful of

    transitive dependencies
  29. Monitor dependencies $ ./gradlew :my-lib:dependencies releaseRuntimeClasspath +- project :my-lib |

    +- org.jetbrains.kotlin:kotlin-stdlib:1.3.61 | +- com.example.something:core-lib:1.2.0 | | \- org.jetbrains.kotlin:kotlin-stdlib:1.3.61 → 1.5.31 (*) 29
  30. Monitor dependencies $ ./gradlew :my-lib:dependencies releaseRuntimeClasspath +- project :my-lib |

    +- org.jetbrains.kotlin:kotlin-stdlib:1.5.31 | +- com.example.something:core-lib:1.2.0 | | \- org.jetbrains.kotlin:kotlin-stdlib:1.3.61 → 1.5.31 (*) 30
  31. Protect experimental features ▪ Use -alpha and -beta releases ▪

    Use Kotlin’s opt-in annotations 31
  32. Kotlin Opt-in annotations 32 @RequiresOptIn(message = "This API is experimental.")

    @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class MyCustomOptIn
  33. Kotlin Opt-in annotations 33 @MyCustomOptIn class MyExperimentalClass { // …

    }
  34. Kotlin Opt-in annotations 34 @OptIn(MyCustomOptIn::class) fun doSomething { val x

    = MyExperimentalClass() // … }
  35. 5 MAKING IT OPEN SOURCE 35

  36. Why an Open Source Library 36 ▪ It lives within

    our customer’s code ▫ Readable ▫ Editable ▪ Allows direct contribution ▪ Keeps the engineering team closer to our users ▪ We also use Open Source every day
  37. Contributing.md 37 ▪ Developer environment (IDE, tools, …) ▪ How

    to build and run the code ▪ How to run the tests / static analysis ▪ How to contribute ▫ Issues ▫ PRs ▪ Coding conventions
  38. PR & Issue templates 38 ▪ Dedicated files ▫ .github/ISSUE_TEMPLATE/bug.md

    ▫ .github/PULL_REQUEST_TEMPLATE.md ▪ Custom checklist for everyone
  39. LICENSE 39 ▪ Use an existing license ▫ https://choosealicense.com/ ▪

    Apache / MIT ▫ Compatible with your dependencies
  40. 6 ANDROID GUIDELINES 40

  41. AndroidManifest.xml 41 <manifest package="com.example.library"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application></application> </manifest>
  42. build.gradle[.kts] 42 android { minSDK = 19 targetSdk = 31

    defaultConfig { aarMetadata { minCompileSdk = 29 } } }
  43. build.gradle[.kts] 43 android { // … testFixtures { // uses

    src/testFixtures enable = true } }
  44. Publish to Maven ▪ Maven Central ▪ Custom Maven Server

    44
  45. Google Play SDK Index 45

  46. CONCLUSION 46

  47. Keep an Open Mindset 47 ▪ Every mistake is a

    lesson ▪ Look at other Open Source Libraries ▫ http://github.com/Datadog/dd-sdk-android
  48. Thank you! ANY QUESTIONS? @xgouchet @datadoghq 48

  49. CREDITS Special thanks to all the people who made and

    released these awesome resources for free: ▪ Presentation template by SlidesCarnival ▪ Photographs by Unsplash 49