From Imperative To Reactive Thinking

From Imperative To Reactive Thinking

B56bb22b3a4b83c6b534b4c114671380?s=128

Todd Motto

July 10, 2017
Tweet

Transcript

  1. None
  2. @ todd motto @ mrja me she nry

  3. None
  4. "REACTIVE THINKING"

  5. "IMPERATIVE THINKING"

  6. DESIGN PATTERNS

  7. None
  8. None
  9. DISCOVERING PATTERNS Ob se rve r Pa tte rn Se

    que nce s a nd O pe ra tors
  10. OBSERVER PATTERN

  11. None
  12. None
  13. None
  14. None
  15. None
  16. None
  17. None
  18. None
  19. Observers Observable

  20. Consumers Producer

  21. SEQUENCES AND OPERATORS

  22. None
  23. Producer Consumer

  24. Producer Pipeline Consumer

  25. Producer Pipeline Consumer

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

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

  28. None
  29. Water

  30. Water heatWater() heatWater()

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

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

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

  34. Consumer Producer Business logic Business logic Consumer

  35. None
  36. None
  37. None
  38. None
  39. None
  40. PATTERNS DISCOVERED Ob se rve r Pa tte rn Se

    que nce s a nd O pe ra tors
  41. None
  42. None
  43. DEMO

  44. Imperative SOLUTION #1:

  45. Elements of our game 1. <div id="james">James</div> 2. <div id="todd">Todd</div>

    3. <div id="ball"></div> 4. 5. <button id="start">Start</button>
  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.
  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
  48. Starting the game 1. function handleClick() { 2. // our

    game code 3. } 4. 5. startBtn.addEventListener('click', handleClick);
  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
  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) {
  51. Core throwing and catching 2. // person1 starts with ball

    1. function throwAndCatchBetween(person1, person2) {
  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.
  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
  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);
  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
  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.
  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
  58. Reactive SOLUTION #2:

  59. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Th rowi ng the ball> 3. Ob se rvable<Ca tchi ng ( or not!) the ball>
  60. Observable<Start button clicks> 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.
  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();
  62. Core throwing and catching 1. // Usage 2. .switchMap( 3.

    handleThrowAndCatchBetween(james, todd) 4. ); 5.
  63. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>
  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...
  65. Observable<Person throwing the ball> 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).
  66. Observable<Person throwing the ball> 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))
  67. Observable<Person throwing the ball> 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;
  68. "Plug in" the throwing for p1 and p2 1. //

    Usage 2. .switchMap( 3. handleThrowAndCatchBetween(james, todd) 4. ); 5.
  69. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>
  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.
  71. Observable<Person catching the ball> 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$
  72. "Plug in" the throwing for p1 and p2 1. //

    Usage 2. .switchMap( 3. handleThrowAndCatchBetween(james, todd) 4. ); 5.
  73. 1. Ob se rvable<S ta rt b utton click s>

    2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>
  74. CODE REVIEW

  75. Thank you! @ to dd motto / @ mr ja

    m e s he nry