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

From Imperative To Reactive Thinking

From Imperative To Reactive Thinking

Todd Motto

July 10, 2017
Tweet

More Decks by Todd Motto

Other Decks in Programming

Transcript

  1. View Slide

  2. @
    todd
    motto
    @
    mrja
    me
    she
    nry

    View Slide

  3. View Slide

  4. "REACTIVE THINKING"

    View Slide

  5. "IMPERATIVE THINKING"

    View Slide

  6. DESIGN PATTERNS

    View Slide

  7. View Slide

  8. View Slide

  9. DISCOVERING PATTERNS
    Ob
    se
    rve
    r Pa
    tte
    rn
    Se
    que
    nce
    s a
    nd O
    pe
    ra
    tors

    View Slide

  10. OBSERVER PATTERN

    View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. View Slide

  19. Observers
    Observable

    View Slide

  20. Consumers
    Producer

    View Slide

  21. SEQUENCES AND OPERATORS

    View Slide

  22. View Slide

  23. Producer
    Consumer

    View Slide

  24. Producer
    Pipeline
    Consumer

    View Slide

  25. Producer
    Pipeline
    Consumer

    View Slide

  26. Producer
    Pipeline
    (Sequence)
    .map()
    .filter()
    Consumer

    View Slide

  27. Producer
    Pipeline
    (Sequence)
    Produces values
    Business logic
    Final outcome
    Consumer

    View Slide

  28. View Slide

  29. Water

    View Slide

  30. Water
    heatWater() heatWater()

    View Slide

  31. Water
    heatWater() heatWater()
    addBeans() addBeans()

    View Slide

  32. Water
    heatWater() heatWater()
    addBeans() addBeans()
    addMilk()

    View Slide

  33. White coffee
    Water
    heatWater() heatWater()
    addBeans() addBeans()
    addMilk() Black coffee

    View Slide

  34. Consumer
    Producer
    Business logic
    Business logic
    Consumer

    View Slide

  35. View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. PATTERNS DISCOVERED
    Ob
    se
    rve
    r Pa
    tte
    rn
    Se
    que
    nce
    s a
    nd O
    pe
    ra
    tors

    View Slide

  41. View Slide

  42. View Slide

  43. DEMO

    View Slide

  44. Imperative
    SOLUTION #1:

    View Slide

  45. Elements of our game
    1. James
    2. Todd
    3.
    4.
    5. Start

    View Slide

  46. Game Helpers
    6. const CHANCE_OF_BAD_THROW = 0.5;
    7.
    8. // Throw affects chances of catching
    9. function checkDropped(isBadThrow): boolean;
    1. // Helpers to move ball around in the game
    2. function addBall(player: Element): void;
    3. function removeBall(player: Element): void;
    4.
    5. // Simple 50/50 chance of bad throw
    We use the throw quality to determine whether the
    ball is caught or not.

    View Slide

  47. TODO
    1. S
    ta
    rt the ga
    me
    on `
    sta
    rtB
    tn` click
    2. Th
    row a
    nd ca
    tch
    the ball be
    twee
    n 2
    pla
    ye
    rs
    3. Check each
    th
    row to see if i
    t wa
    s “bad”
    4. Check ca
    tch, e
    ndi
    ng
    the ga
    me
    on d
    rop

    View Slide

  48. Starting the game
    1. function handleClick() {
    2. // our game code
    3. }
    4.
    5. startBtn.addEventListener('click', handleClick);

    View Slide

  49. TODO
    1. S
    ta
    rt the ga
    me
    on `
    sta
    rtB
    tn` click
    2. Th
    row a
    nd ca
    tch
    the ball be
    twee
    n 2
    pla
    ye
    rs
    3. Check each
    th
    row to see if i
    t wa
    s “bad”
    4. Check ca
    tch, e
    ndi
    ng
    the ga
    me
    on d
    rop

    View Slide

  50. 5. // TODO
    6. // - person1 starts with ball
    7. // - wait while they get ready to throw
    1. // Our two refs to the people DOM nodes
    2. throwAndCatchBetween(james, todd);
    3.
    4. function throwAndCatchBetween(person1, person2) {

    View Slide

  51. Core throwing and catching
    2. // person1 starts with ball
    1. function throwAndCatchBetween(person1, person2) {

    View Slide

  52. ...now for humans
    1. function throwAndCatchBetween(person1, person2) {
    2. // person1 starts with ball
    3. addBall(person1);
    4.
    5. // wait while they get ready to throw
    6. setTimeout(() => {
    7.
    8. // person1 throws ball
    9. removeBall(person1);
    10.
    11. // ball travels through the air
    12. setTimeout(() => {
    13.
    14. // person2 catches ball
    15. addBall(person2);
    16.
    17. // Back again!
    18. throwAndCatchBetween(person2, person1);
    19.
    Ball flies throught the air for 1 second before being
    caught.

    View Slide

  53. TODO
    1. S
    ta
    rt the ga
    me
    on `
    sta
    rtB
    tn` click
    2. Th
    row a
    nd ca
    tch
    the ball be
    twee
    n 2
    pla
    ye
    rs
    3. Check each
    th
    row to see if i
    t wa
    s “bad”
    4. Check ca
    tch, e
    ndi
    ng
    the ga
    me
    on d
    rop

    View Slide

  54. Check throw quality
    8. // person1 throws ball
    9. removeBall(person1);
    10. // capture if throw was bad
    11. const isBadThrow =
    12. Math.random() <= CHANCE_OF_BAD_THROW;
    1. function throwAndCatchBetween(person1, person2) {
    2. // person1 starts with ball
    3. addBall(person1);
    4.
    5. // wait while they get ready to throw
    6. setTimeout(() => {
    7.
    13.
    14. // ball travels through the air
    15. setTimeout(() => {
    16.
    17. // person2 catches ball
    18. addBall(person2);
    19.
    20. // Back again!
    21. throwAndCatchBetween(person2, person1);

    View Slide

  55. TODO
    1. S
    ta
    rt the ga
    me
    on `
    sta
    rtB
    tn` click
    2. Th
    row a
    nd ca
    tch
    the ball be
    twee
    n 2
    pla
    ye
    rs
    3. Check each
    th
    row to see if i
    t wa
    s “bad”
    4. Check ca
    tch, e
    ndi
    ng
    the ga
    me
    on d
    rop

    View Slide

  56. Check if ball was dropped
    10. // capture if throw was bad
    11. const isBadThrow =
    12. Math.random() <= CHANCE_OF_BAD_THROW;
    13.
    14. // ball travels through the air
    15. setTimeout(() => {
    16.
    17. if (checkDropped(isBadThrow)) {
    18. return // Game over: Ball dropped
    19. }
    3. addBall(person1);
    4.
    5. // wait while they get ready to throw
    6. setTimeout(() => {
    7.
    8. // person1 throws ball
    9. removeBall(person1);
    20.
    21. // person2 catches ball
    22. addBall(person2);
    23.
    24. // Back again!
    25. throwAndCatchBetween(person2, person1);
    26.

    View Slide

  57. 1. S
    ta
    rt the ga
    me
    on `
    sta
    rtB
    tn` click
    2. Th
    row a
    nd ca
    tch
    the ball be
    twee
    n 2
    pla
    ye
    rs
    3. Check each
    th
    row to see if i
    t wa
    s “bad”
    4. Check ca
    tch, e
    ndi
    ng
    the ga
    me
    on d
    rop

    View Slide

  58. Reactive
    SOLUTION #2:

    View Slide

  59. TODO
    1. Ob
    se
    rvableta
    rt b
    utton click
    s>
    2. Ob
    se
    rvablerowi
    ng
    the ball>
    3. Ob
    se
    rvabletchi
    ng (
    or not!)
    the ball>

    View Slide

  60. Observable
    6. // Start listening for clicks
    7. game$.subscribe();
    1. const startClick$ = Rx.Observable
    2. .fromEvent(startBtn, 'click');
    3.
    4. const game$ = startClick$;
    5.
    We subscribe to the Observable to begin actually
    listening for the start button click events.

    View Slide

  61. Turn a click into throw and catch!
    4. const game$ = startClick$
    5. .switchMap(
    6. handleThrowAndCatchBetween(james, todd)
    7. );
    1. const startClick$ = Rx.Observable
    2. .fromEvent(startBtn, 'click');
    3.
    8.
    9. // Start listening for clicks
    10. game$.subscribe();

    View Slide

  62. Core throwing and catching
    1. // Usage
    2. .switchMap(
    3. handleThrowAndCatchBetween(james, todd)
    4. );
    5.

    View Slide

  63. TODO
    1. Ob
    se
    rvableta
    rt b
    utton click
    s>
    2. Ob
    se
    rvablerson th
    rowi
    ng
    the ball>
    3. Ob
    se
    rvablerson ca
    tchi
    ng
    the ball>

    View Slide

  64. What events make up a "throw"?
    1. // person1 starts with ball
    2. addBall(person1);
    3.
    4. // wait while they get ready to throw
    5. setTimeout(() => {
    6.
    7. // person1 throws ball
    8. // capture if throw was bad
    9. removeBall(person1);
    10. const isBadThrow =
    11. Math.random() <= CHANCE_OF_BAD_THROW;
    12.
    We can extract the relevant concepts from our
    imperative example...

    View Slide

  65. Observable
    1. // capture if throw was bad
    2. const isBadThrow =
    3. Math.random() <= CHANCE_OF_BAD_THROW;
    4.
    5. const throw$ = Rx.Observable.of(isBadThrow);
    We can make our initial throw$ stream encapsulate the
    throw quality (so we can evaluate it later).

    View Slide

  66. Observable
    9. // ball travels through the air
    10. .delay(1000);
    1. // capture if throw was bad
    2. const throw$ = Rx.Observable.of(isBadThrow)
    3. // person1 starts with ball
    4. .do(() => addBall(person1))
    5. // wait while they get ready to throw
    6. .delay(1000)
    7. // person1 throws ball
    8. .do(() => removeBall(person1))

    View Slide

  67. Observable
    4. return Rx.Observable.of(isBadThrow)
    5. .do(() => addBall(person))
    6. .delay(1000)
    7. .do(() => removeBall(person))
    8. .delay(1000);
    9. }
    1. function handleThrow$From(person) {
    2. const isBadThrow =
    3. Math.random() <= CHANCE_OF_BAD_THROW;

    View Slide

  68. "Plug in" the throwing for p1 and p2
    1. // Usage
    2. .switchMap(
    3. handleThrowAndCatchBetween(james, todd)
    4. );
    5.

    View Slide

  69. TODO
    1. Ob
    se
    rvableta
    rt b
    utton click
    s>
    2. Ob
    se
    rvablerson th
    rowi
    ng
    the ball>
    3. Ob
    se
    rvablerson ca
    tchi
    ng
    the ball>

    View Slide

  70. What events make up a "catch"?
    5. // Ball is caught succesfully
    6. return Rx.Observable.of('')
    7. .do(() => addBall(person))
    1. // Ball is dropped
    2. if (checkDropped(isBadThrow)) {
    3. return Rx.Observable.throw(`Ball dropped`)
    4. }
    If the ball is caught, we return an Observable (the
    value isn't important) and add the ball to the person
    as normal.

    View Slide

  71. Observable
    2. // The returned function will be used within
    1. function handleCatch$By(person) {
    The `isBadThrow` value will be passed in via the
    switchMap from the previous throw$

    View Slide

  72. "Plug in" the throwing for p1 and p2
    1. // Usage
    2. .switchMap(
    3. handleThrowAndCatchBetween(james, todd)
    4. );
    5.

    View Slide

  73. 1. Ob
    se
    rvableta
    rt b
    utton click
    s>
    2. Ob
    se
    rvablerson th
    rowi
    ng
    the ball>
    3. Ob
    se
    rvablerson ca
    tchi
    ng
    the ball>

    View Slide

  74. CODE REVIEW

    View Slide

  75. Thank you!
    @
    to
    dd
    motto
    / @
    mr
    ja
    m
    e
    s
    he
    nry

    View Slide