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

How to write a safe and reliable Open Source Library

How to write a safe and reliable 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

April 22, 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 thousands devices
  9. Ensure the code is safe 9 ▪ objective zero crash

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

    Kotlin syntax ▫ check ▫ require ▫ !! ▪ List all third party methods throwing exceptions 10
  11. Mandatory Code Review ▪ Notice potential issues early ▪ Increase

    readability ▪ Generate discussion ▫ Data structure ▫ Design Patterns ▫ Third party libraries 11
  12. “Testing is doubting!” 12

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

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

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

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

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

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

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

    impact for each update
  20. 3 MAKING IT USABLE 20

  21. Opt-in or opt-out by default 21 ▪ 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
  22. Every thing can be configured ▪ Allow enabling/disabling individual features

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

    configure everything right now… ▪ … or ever
  24. 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 24
  25. 4 MAKING IT FUTURE PROOF 25

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

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

    transitive dependencies
  28. 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 (*) 28
  29. 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 (*) 29
  30. Protect experimental features ▪ Use -alpha and -beta releases ▪

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

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

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

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

  35. Why an Open Source Library 35 ▪ 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
  36. Contributing.md 36 ▪ 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
  37. PR & Issue templates 37 ▪ Dedicated files ▫ .github/ISSUE_TEMPLATE/bug.md

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

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

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

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

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

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

    43
  44. CONCLUSION 44

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

    lesson ▪ Look at other Open Source Libraries
  46. Thank you! ANY QUESTIONS? @xgouchet @datadoghq 46

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

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