$30 off During Our Annual Pro Sale. View Details »

Building SDKs - The Kotlin Way

Building SDKs - The Kotlin Way

by Jossi Wolf
presented on August 30, 2019 @Kotlin/Everywhere Hamburg

Kotlin User Group Hamburg

August 30, 2019
Tweet

More Decks by Kotlin User Group Hamburg

Other Decks in Programming

Transcript

  1. View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. Project Manager
    Developer
    Hey could you ship the
    new SDK version?

    View Slide

  6. Project Manager
    Developer
    Hey could you ship the
    new SDK version?
    S-s-sure…

    View Slide

  7. $ gradlew sdk:assembleRelease
    $ building…
    $ …
    $ # 10 hours later

    View Slide

  8. 3. Blah blah bla
    2. Bla blah bla
    1. Blah blah blah
    RELEASE
    NOTES

    View Slide

  9. 4. EXPERIMENTAL APIs.
    They are subject to
    change and not final!!!
    3. Blah blah bla
    2. Bla blah bla
    1. Blah blah blah
    RELEASE
    NOTES

    View Slide

  10. Project Manager
    Developer
    Cool, thanks
    Here’s the new
    Version!
    SDK

    View Slide

  11. 4. APIs have been removed.
    3. Blah blah bla
    2. Bla blah bla
    1. Blah blah blah
    RELEASE
    NOTES

    View Slide

  12. Project Manager
    Developer
    Cool, thanks
    Here’s the new
    Version!
    SDK

    View Slide

  13. Slack Message
    PROJECT MANAGER
    $CUSTOMER JUST CALLED THEY HAVE A BUILD
    ERROR WITH THE NEW SDK VERSION CAN YOU FIX
    THAT NOW PLS
    Friday, 9PM

    View Slide

  14. You: Have they read the release notes?
    PM: I’ll ask
    ...
    PM: No

    View Slide

  15. @Experimental
    @Deprecated

    View Slide

  16. @Target(ANNOTATION_CLASS)
    public annotation class Experimental(val level: Level =
    Level.ERROR) {
    public enum class Level {
    WARNING,
    ERROR,
    }
    }

    View Slide

  17. @Target(ANNOTATION_CLASS)
    public annotation class Experimental(val level: Level =
    Level.ERROR) {
    public enum class Level {
    WARNING,
    ERROR,
    }
    }

    View Slide

  18. @Target(ANNOTATION_CLASS)
    public annotation class Experimental(val level: Level =
    Level.ERROR) {
    public enum class Level {
    WARNING,
    ERROR,
    }
    }

    View Slide

  19. @Experimental
    annotation class ExperimentalCatPicturesAPI

    View Slide

  20. class CatPicturesAPI {
    /**
    * Experimental in case cats overtake the planet and
    * demand pets and treats in exchange for cat pictures
    */
    @ExperimentalCatPicturesAPI
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  21. fun doCatPictureAPIStuff() {
    val catPicturesAPI = CatPicturesAPI()
    catPicturesAPI.getCatPicture()
    } This API is experimental and its usage
    must be marked with @UseExperimental.

    View Slide

  22. @ExperimentalCatPicturesAPI
    fun doCatPictureAPIStuff() {
    val catPicturesAPI = CatPicturesAPI()
    catPicturesAPI.getCatPicture()
    }

    View Slide

  23. @UseExperimental(ExperimentalCatPicturesAPI::class)
    fun doCatPictureAPIStuff() {
    val catPicturesAPI = CatPicturesAPI()
    catPicturesAPI.getCatPicture()
    }

    View Slide

  24. Productive Developer

    View Slide

  25. Project Man
    Developer

    View Slide

  26. Project Manager
    Developer

    View Slide

  27. Project Manager
    Developer

    View Slide

  28. Project Manager
    Developer

    View Slide

  29. Project Manager
    Developer
    Hey could you ship the
    new SDK version?

    View Slide

  30. Project Manager
    Developer
    Hey could you ship the
    new SDK version?
    S-s-sure…

    View Slide

  31. 4. APIs have been
    deprecated.
    3. Blah blah bla
    2. Bla blah bla
    1. Blah blah blah
    RELEASE
    NOTES

    View Slide

  32. Project Manager
    Developer
    Cool, thanks
    Here’s the new
    Version!
    SDK
    Contains
    deprecated APIs

    View Slide

  33. Project Manager
    Cool, thanks
    SDK User
    Here’s the new
    Version!
    SDK
    Contains
    deprecated APIs

    View Slide

  34. BUILD ERROR
    SDK User
    SDK
    *updates SDK version*
    *runs Gradle build*

    View Slide

  35. /**
    * Marks the annotated declaration as deprecated.
    */ TYPEALIAS)
    annotation class Deprecated(
    val message: String,
    val replaceWith: ReplaceWith = ReplaceWith(""),
    val level: DeprecationLevel = DeprecationLevel.WARNING
    )

    View Slide

  36. @Deprecated(“This is a legacy API. Please use
    the new CatPicturesAPI instead.")
    class LegacyCatPictureAPI {
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  37. val api = LegacyCatPictureAPI()

    View Slide

  38. /**
    * Marks the annotated declaration as deprecated.
    */ TYPEALIAS)
    annotation class Deprecated(
    val message: String,
    val replaceWith: ReplaceWith = ReplaceWith(""),
    val level: DeprecationLevel = DeprecationLevel.WARNING
    )

    View Slide

  39. annotation class ReplaceWith(
    val expression: String,
    vararg val imports: String
    )

    View Slide

  40. @Deprecated(
    "This is a legacy API. Please use the new
    CatPicturesAPI instead.",
    ReplaceWith("CatPicturesAPI")
    )
    class LegacyCatPictureAPI {
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  41. @Deprecated(
    "This is a legacy API. Please use the new
    CatPicturesAPI instead.",
    ReplaceWith("CatPicturesAPI")
    )
    class LegacyCatPictureAPI {
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  42. val api = LegacyCatPictureAPI()
    Replace with ‘CatPicturesAPI’

    View Slide

  43. val api = LegacyCatPictureAPI()
    Replace with ‘CatPicturesAPI’
    Alt + Enter

    View Slide

  44. val api = CatPicturesAPI()
    ✔Occurrence Replaced!

    View Slide

  45. class Laboratory {
    fun getRandommChemical(): Chemical
    = randomExperiment + randomExperiment + explosive
    }

    View Slide

  46. class Laboratory {
    @Deprecated(
    "Typo in here. Please use getRandomChemical instead.",
    ReplaceWith("getRandomChemical")
    )
    fun getRandommChemical(): Chemical
    = randomExperiment + randomExperiment + explosive
    }

    View Slide

  47. class Laboratory {
    @Deprecated(
    "Typo in here. Please use getRandomChemical instead.",
    ReplaceWith("getRandomChemical")
    )
    fun getRandommChemical(): Chemical
    = randomExperiment + randomExperiment + explosive
    fun getRandomChemical(): Chemical
    = randomExperiment + randomExperiment + explosive
    }

    View Slide

  48. class Laboratory {
    @Deprecated(
    "Typo in here. Please use getRandomChemical instead.",
    ReplaceWith("getRandomChemical")
    )
    fun getRandommChemical(): Chemical
    = getRandomChemical()
    fun getRandomChemical(): Chemical
    = randomExperiment + randomExperiment + explosive
    }

    View Slide

  49. class CatPicturesAPI {
    /**
    * Experimental in case cats overtake the planet and
    * demand pets and treats in exchange for cat pictures
    */
    @ExperimentalCatPicturesAPI
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  50. class CatPictureAPI {
    /**
    * Experimental in case cats overtake the planet and
    * demand pets and treats in exchange for cat pictures
    */
    @ExperimentalCatPicturesAPI
    fun getCatPicture(): CatPicture = CatPicture()
    }

    View Slide

  51. @Deprecated(
    message = "CatPicturesAPI has been renamed
    to CatPictureAPI“,
    replaceWith = ReplaceWith("CatPictureAPI")
    )
    typealias CatPicturesAPI = CatPictureAPI

    View Slide

  52. View Slide

  53. SDK

    View Slide

  54. interface SDKCapabilities {
    ...
    }
    class ArtboardSDK: SDKCapabilities {
    //It'll become super bloated
    }

    View Slide

  55. interface CanvasCapabilities
    interface SDKCapabilities: CanvasCapabilities
    class ArtboardSDK: SDKCapabilities {
    val canvasManager = CanvasManager()
    override fun draw() = canvasManager.draw()
    }

    View Slide

  56. interface CanvasCapabilities
    interface SDKCapabilities: CanvasCapabilities
    class ArtboardSDK: SDKCapabilities {
    val canvasManager = CanvasManager()
    override fun draw() = canvasManager.draw()
    }

    View Slide

  57. interface CanvasCapabilities
    interface SDKCapabilities: CanvasCapabilities
    class ArtboardSDK: SDKCapabilities {
    val canvasManager = CanvasManager()
    override fun draw() = canvasManager.draw()
    }

    View Slide

  58. interface CanvasCapabilities
    interface SDKCapabilities: CanvasCapabilities
    class CanvasManager: CanvasCapabilities
    class ArtboardSDK:
    SDKCapabilities,
    CanvasCapabilities by CanvasManager()

    View Slide

  59. interface CanvasCapabilities
    interface SDKCapabilities: CanvasCapabilities
    class CanvasManager: CanvasCapabilities
    class ArtboardSDK:
    SDKCapabilities,
    CanvasCapabilities by CanvasManager()

    View Slide

  60. View Slide

  61. View Slide

  62. View Slide