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.

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

    View Slide

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

    View Slide

  3. 3

    View Slide

  4. 0
    Introduction
    4

    View Slide

  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

    View Slide

  6. Repository statistics
    - 2400+ commits
    - 3 developers
    - 20+ contributors
    - (internal and community)
    - 30 published versions
    - 10 libraries
    6

    View Slide

  7. 1
    MAKING IT SAFE
    7

    View Slide

  8. Reliability is key
    8
    ▪ Library lives in hundreds apps…
    ▪ … deployed on thousands devices

    View Slide

  9. Ensure the code is safe
    9
    ▪ objective zero crash
    ▫ Static Analysis
    ▫ Code review
    ▫ *-tests
    ▪ Real life use cases

    View Slide

  10. Static analysis (Detekt)
    ▪ Forbid throwing exceptions
    ▪ Forbid specific Kotlin syntax
    ▫ check
    ▫ require
    ▫ !!
    ▪ List all third party methods throwing
    exceptions
    10

    View Slide

  11. Mandatory Code Review
    ▪ Notice potential issues early
    ▪ Increase readability
    ▪ Generate discussion
    ▫ Data structure
    ▫ Design Patterns
    ▫ Third party libraries
    11

    View Slide

  12. “Testing is doubting!”
    12

    View Slide

  13. Unit/Integration/End-to-end Testing
    ▪ Strict policy on the coverage
    ▪ Deal with flaky test ASAP
    ▪ Stay confident in our tests
    13

    View Slide

  14. Real life use cases
    ▪ Dogfooding in our own apps
    ▪ Regular tests using OSS apps
    ▫ Wikipedia
    ▫ Reddit client
    ▫ HackerNews client
    14

    View Slide

  15. Respect privacy
    15
    ▪ Leverage Sandbox storage / Cache
    ▪ Add GDPR option
    ▪ Write doc about Data Collection

    View Slide

  16. 2
    MAKING IT EFFICIENT
    16

    View Slide

  17. Limit library performance impact
    17
    ▪ Offload heavy computation to background
    threads/workers
    ▪ Track Memory Leaks

    View Slide

  18. Monitor library overhead
    18
    ▪ Compute the impact of the library on
    ▫ CPU
    ▫ Memory
    ▫ Network
    ▫ …

    View Slide

  19. Keep a focus on performance
    19
    ▪ Track the performance impact for each
    update

    View Slide

  20. 3
    MAKING IT USABLE
    20

    View Slide

  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

    View Slide

  22. Every thing can be configured
    ▪ Allow enabling/disabling individual
    features
    ▪ Allow tweaking sampling rates,
    thresholds, …
    22

    View Slide

  23. Use sensible defaults
    23
    ▪ New customers don’t need to configure
    everything right now…
    ▪ … or ever

    View Slide

  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

    View Slide

  25. 4
    MAKING IT FUTURE PROOF
    25

    View Slide

  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

    View Slide

  27. Monitor dependencies
    27
    ▪ Review changelogs
    ▪ Be mindful of transitive dependencies

    View Slide

  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

    View Slide

  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

    View Slide

  30. Protect experimental features
    ▪ Use -alpha and -beta releases
    ▪ Use Kotlin’s opt-in annotations
    30

    View Slide

  31. Kotlin Opt-in annotations
    31
    @RequiresOptIn(message = "This API is experimental.")
    @Retention(AnnotationRetention.BINARY)
    @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
    annotation class MyCustomOptIn

    View Slide

  32. Kotlin Opt-in annotations
    32
    @MyCustomOptIn
    class MyExperimentalClass {
    // …
    }

    View Slide

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

    View Slide

  34. 5
    MAKING IT OPEN SOURCE
    34

    View Slide

  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

    View Slide

  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

    View Slide

  37. PR & Issue templates
    37
    ▪ Dedicated files
    ▫ .github/ISSUE_TEMPLATE/bug.md
    ▫ .github/PULL_REQUEST_TEMPLATE.md
    ▪ Custom checklist for everyone

    View Slide

  38. LICENSE
    38
    ▪ Use an existing license
    ▫ https://choosealicense.com/
    ▪ Apache / MIT
    ▫ Compatible with your dependencies

    View Slide

  39. 6
    ANDROID GUIDELINES
    39

    View Slide

  40. AndroidManifest.xml
    40

    android:name="android.permission.INTERNET" />
    android:name="android.permission.ACCESS_NETWORK_STATE" />


    View Slide

  41. build.gradle[.kts]
    41
    android {
    minSDK = 19
    targetSdk = 31
    defaultConfig {
    aarMetadata {
    minCompileSdk = 29
    }
    }
    }

    View Slide

  42. build.gradle[.kts]
    42
    android {
    // …
    testFixtures {
    // uses src/testFixtures
    enable = true
    }
    }

    View Slide

  43. Publish to Maven
    ▪ Maven Central
    ▪ Custom Maven Server
    43

    View Slide

  44. CONCLUSION
    44

    View Slide

  45. Keep an Open Mindset
    45
    ▪ Every mistake is a lesson
    ▪ Look at other Open Source Libraries

    View Slide

  46. Thank you!
    ANY QUESTIONS?
    @xgouchet
    @datadoghq
    46

    View Slide

  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

    View Slide