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

Simplify your UI management with (algebraic da...

Simplify your UI management with (algebraic data) types

With higher and higher user expectations and a rapid technological evolution, the web platform complexity has exploded.
If we use JavaScript, it might be difficult to manage richer client-side features and larger codebase. With ReScript (ReasonML) concepts, we'll see with a few practical examples how algebraic data-types can help us represent more efficiently and simply the different states in our interfaces, while avoiding bugs.

https://github.com/bloodyowl/2021-01-types-talk

Matthias Le Brun

February 03, 2021
Tweet

More Decks by Matthias Le Brun

Other Decks in Technology

Transcript

  1. Matthias Le Brun Head of Product Design @ BeOp Co-founder

    & podcast host @ Putain de Code ! Twitter, GitHub: @bloodyowl
  2. A new kind of advertising We're looking for a Back-End

    Developer (Clojure, Java, Kotlin) and a DevOps (AWS)!
  3. 3 things you need to deal in almost any UI

    application: 1. Optionality 2. Success 3. Requests
  4. «We want to push a notification to motivate the user

    if they have some days with low or no activity in the last 30 days» — the product team
  5. let activitySummaryByDay: array<maybeActivity> undefined / / no activity recorded for

    the day type dayActivity = { calories: int, workoutDuration: int, standUpHours: int, } / / some activity
  6. undefined None matched the predicate? → all days f i

    lled and > 50cal A matching empty day ? → one day with no recorded data
  7. let find: ( array<'a | undefined>, 'a | undefined =

    > bool ) = > 'a | undefined | undefined
  8. let find: ( array<'a | undefined>, 'A | undefined =

    > bool ) = > 'a | undefined | undefined undefined
  9. let index = last30daysActivity.findIndex(item = > item = = undefined

    | | item.calories < 50 ); if(index = = -1) { / / not found } else { let item = last30daysActivity[index]; if(item = = undefined) { / / found day without recorded activity } else { / / found day with low activity } } The "correct" way exposes implementation details
  10. type option<'a> = | Some('a) | None Option is a

    container, holding a value or nothing
  11. last30daysActivity - > find(item = > switch item { |

    None = > true | Some({calories}) when calories < 50 = > true | _ = > false })
  12. None / / No match Some(None) / / Found an

    empty day Some(Some(x)) / / Found a filled day Do your f**king 10 000 steps
  13. / / BE CAREFUL ! ! ! / / Throws

    an error let f: 'param = > 'success;
  14. try { let x = f() handleSuccess(x) } catch(err) {

    handleFailure(err) } More codepaths, no idea where it's going to be handled or if it is
  15. switch f() { | Ok(x) = > handleSuccess(x) | Error(err)

    = > handleFailure(err) } You need to handle the possibility of error if you want to extract the value
  16. setValue(_ = > result) / / then switch value {

    | Ok(value) = > <Success value / > | Error(error) = > <ErrorMessage error / > } You can pass around and store the result for later extraction
  17. type state = { isLoading: true | false, error: error

    | null, data: data | null } 2 2 2
  18. isLoading error data FALSE NULL NULL TRUE NULL NULL FALSE

    ERROR NULL FALSE NULL DATA TRUE TRUE NULL TRUE FALSE DATA FALSE TRUE DATA TRUE TRUE DATA Not asked yet Loading Done with error Done with success
  19. SUM TYPES A + B + C → OR PRODUCT

    TYPES A * B * C → AND Algebraic data types
  20. switch (resource) { | NotAsked = > "" | Loading

    = > "Loading . . . " | Done(Ok(value)) = > "Loaded: " + + value | Done(Error(_)) = > "An error occurred" }
  21. 25 ┆ < / button> 26 ┆ <br / >

    27 ┆ {switch user { 28 ┆ | NotAsked | Loading = > React.null . ┆ . . . 37 ┆ | Done(Ok(None)) = > "No result was received" - > React 38 ┆ }} 39 ┆ < / > 40 ┆ } You forgot to handle a possible case here, for example: Done (Error _)
  22. Thank you! Questions? Matthias Le Brun Lead front-end developer @

    BeOp Co-founder & podcast host @ Putain de Code ! Twitter, GitHub: @bloodyowl