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

The Case of the Vanished Variable – A Ruby Mystery Story

Nadia Odunayo
December 08, 2022
71

The Case of the Vanished Variable – A Ruby Mystery Story

After a stressful couple of days at work, Deirdre Bug is looking forward to a quiet evening in. But her plans are thwarted when the phone rings. “I know I’m the last person you want to hear from…but...I need your help!” Follow Deirdre as she embarks on an adventure that features a looming Demo Day with serious prize money up for grabs, a trip inside the walls of one of the Ruby community’s most revered institutions, and some broken code that appears to be much more simple than meets the eye.

Nadia Odunayo

December 08, 2022
Tweet

Transcript

  1. THE CASE OF THE
    VANISHED VARIABLE
    A Ruby Mystery Story
    Nadia Odunayo, @nodunayo

    View full-size slide

  2. 3 million unique
    visitors per month

    View full-size slide

  3. 36 million pageviews
    per month

    View full-size slide

  4. 110 million requests
    per month

    View full-size slide

  5. 💰💰💰

    View full-size slide

  6. 💰💰💰

    View full-size slide

  7. Nadia Odunayo

    View full-size slide

  8. Nadia Odunayo

    View full-size slide

  9. CASE FILES #048

    View full-size slide

  10. CASE FILES #048
    Vanished Variable

    View full-size slide

  11. I know I’m the last
    person you want
    to hear from…

    View full-size slide

  12. …but I need your
    help!

    View full-size slide

  13. …but I need your
    help!
    👱

    View full-size slide

  14. Jenny
    • 29 years old
    👱

    View full-size slide

  15. Jenny
    • 29 years old
    • Ruby developer
    👱

    View full-size slide

  16. Jenny
    • 29 years old
    • Ruby developer
    • Rails obsessed
    👱

    View full-size slide

  17. Jenny
    • 29 years old
    • Ruby developer
    • Rails obsessed
    👱
    • Betrayed her best friend

    View full-size slide

  18. Ruby Institute of Professionals

    View full-size slide

  19. RIP
    Ruby Institute of Professionals

    View full-size slide

  20. Incubator
    RIP

    View full-size slide

  21. Incubator
    • Help Ruby’s image
    RIP

    View full-size slide

  22. Incubator
    • Help Ruby’s image
    • Startup ideas
    RIP

    View full-size slide

  23. Incubator
    • Help Ruby’s image
    • Startup ideas
    • $500k prize
    RIP

    View full-size slide

  24. Incubator
    • Help Ruby’s image
    • Startup ideas
    • $500k prize
    • Jenny’s team in
    fi
    nal two
    RIP

    View full-size slide

  25. We’re building a
    platform that assigns
    grants…
    👱

    View full-size slide

  26. There are three
    different types of
    award…
    👱

    View full-size slide

  27. Our demo simulates
    an example draw…
    👱

    View full-size slide

  28. …but our code
    has a bug!
    👱

    View full-size slide

  29. It’s so close between
    the
    fi
    nal two teams…
    👱

    View full-size slide

  30. We need you.
    👱

    View full-size slide

  31. 💰💰💰

    View full-size slide

  32. 💰💰💰

    View full-size slide

  33. I don’t need help.
    🧔

    View full-size slide

  34. But, Alex…!
    👱

    View full-size slide

  35. I’ll tell you what,
    Alex…
    🕵

    View full-size slide

  36. …you’ll
    fi
    nd the bug
    quicker!
    🕵

    View full-size slide

  37. There’s
    con
    fi
    dential code
    in here!
    🧔

    View full-size slide

  38. 40 minutes later…

    View full-size slide

  39. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  40. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  41. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  42. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  43. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  44. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  45. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  46. @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb
    class AwardA < Grant

    View full-size slide

  47. @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_b.rb

    View full-size slide

  48. @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_b.rb
    class AwardB < Grant

    View full-size slide

  49. @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_c.rb

    View full-size slide

  50. @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_c.rb
    class AwardC < Grant

    View full-size slide

  51. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  52. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  53. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  54. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  55. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  56. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  57. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  58. 50.times do
    AwardA.assign!
    end
    assign_a.rb

    View full-size slide

  59. 30.times do
    AwardB.assign!
    end
    assign_b.rb

    View full-size slide

  60. 20.times do
    AwardC.assign!
    end
    assign_c.rb

    View full-size slide

  61. puts Grant.award_count
    puts Grant.awards_remaining
    Grant.assign_remaining!
    redraw.rb

    View full-size slide

  62. puts Grant.award_count
    puts Grant.awards_remaining
    Grant.assign_remaining!
    redraw.rb

    View full-size slide

  63. class Grant

    MAX_GRANTS = 100
    @award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  64. 50.times do
    AwardA.assign!
    end

    View full-size slide

  65. 50.times do
    AwardA.assign!
    end

    View full-size slide

  66. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +

    View full-size slide

  67. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +

    View full-size slide

  68. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +

    View full-size slide

  69. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +

    View full-size slide

  70. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +
    =

    View full-size slide

  71. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +
    =
    100

    View full-size slide

  72. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +
    =
    100
    =

    View full-size slide

  73. 50.times do
    AwardA.assign!
    end
    30.times do
    AwardB.assign!
    end
    +
    20.times do
    AwardC.assign!
    end
    +
    =
    100
    =
    MAX_GRANTS

    View full-size slide

  74. Following so far…?
    🧔

    View full-size slide

  75. I got it.
    🕵

    View full-size slide

  76. alex:rip_grant_program/ $

    View full-size slide

  77. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    300
    Awards left to assign:
    -200
    ERROR: Maximum number of grants exceeded!

    View full-size slide

  78. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    300
    Awards left to assign:
    -200
    ERROR: Maximum number of grants exceeded!

    View full-size slide

  79. CHAPTER THREE

    View full-size slide

  80. @award_count

    View full-size slide

  81. class AwardA < Grant
    @award_count = 0

    end

    View full-size slide

  82. class AwardA < Grant
    @award_count = 0

    end
    class AwardB < Grant
    @award_count = 0

    end

    View full-size slide

  83. class AwardA < Grant
    @award_count = 0

    end
    class AwardB < Grant
    @award_count = 0

    end
    class AwardC < Grant
    @award_count = 0

    end

    View full-size slide

  84. class AwardA < Grant
    @award_count = 0

    end
    class AwardB < Grant
    @award_count = 0

    end
    class AwardC < Grant
    @award_count = 0

    end
    class Grant

    MAX_GRANTS = 100
    @award_count = 0

    end

    View full-size slide

  85. What if each class
    were to have a
    differently-named
    class instance
    variable?
    🕵

    View full-size slide

  86. Sure…we can try
    that.
    🧔

    View full-size slide

  87. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  88. class AwardA < Grant
    @award_a_count = 0
    def self.award_count
    @award_a_count
    end


    def self.assign!
    @award_a_count += 1
    end
    end
    award_a.rb

    View full-size slide

  89. class AwardA < Grant
    @award_a_count = 0
    def self.award_count
    @award_a_count
    end


    def self.assign!
    @award_a_count += 1
    end
    end
    award_a.rb

    View full-size slide

  90. alex:rip_grant_program/ $

    View full-size slide

  91. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    300
    Awards left to assign:
    -200
    ERROR: Maximum number of grants exceeded!

    View full-size slide

  92. Alex! You’ll never
    guess who’s in the
    of
    fi
    ce!
    🧑🦱

    View full-size slide

  93. Matz!
    🧑🦱

    View full-size slide

  94. 🏃💨
    💰💰💰
    💰💰💰
    💰💰💰

    View full-size slide

  95. $ git status

    View full-size slide

  96. +++ b/assign_c.rb
    @@ -0,0 +1,151 @@

    View full-size slide

  97. +++ b/assign_c.rb
    @@ -0,0 +1,151 @@

    View full-size slide

  98. 20.times do
    AwardC.assign!
    end
    assign_c.rb

    View full-size slide

  99. class Grant
    @award_count = 300
    def self.award_count
    @award_count
    end
    end

    View full-size slide

  100. What are you
    looking at?
    🧔

    View full-size slide

  101. Where did you get
    my old code from?
    🧔

    View full-size slide

  102. That’s from an old
    demo.
    🧔

    View full-size slide

  103. It was at the bottom
    of this
    fi
    le…
    🕵

    View full-size slide

  104. …you never do partial
    commits?
    🕵

    View full-size slide

  105. c
    c
    c c c
    G
    G G G G
    @
    @ @ @ @ @ @
    @ @
    @ @ @
    =
    d
    d
    d
    s
    s
    s
    s
    .a
    a
    a
    a a a
    a a
    a a a
    @
    @ @ @ @ @ @
    @ @
    @ @ @
    e
    e e
    e
    e e

    View full-size slide

  106. alex:rip_grant_program/ $

    View full-size slide

  107. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    100
    Awards left to assign:
    0
    SUCCESS: All awards assigned!

    View full-size slide

  108. CHAPTER FOUR

    View full-size slide

  109. I’m not the “told-
    you-so” type,
    but…
    👱

    View full-size slide

  110. ….I knew him using
    class variables was
    a bad idea!
    👱

    View full-size slide

  111. 🕵
    You mean
    class instance
    variables!

    View full-size slide

  112. 🕵
    You mean
    class instance
    variables!
    👱
    No, class
    variables!

    View full-size slide

  113. 🕵
    You mean
    class instance
    variables!
    👱
    No, class
    variables!
    🕵
    You don’t
    mean class
    instance
    variables?

    View full-size slide

  114. @@award_count

    View full-size slide

  115. @award_count

    View full-size slide

  116. Do you have time to
    come back upstairs?
    👱

    View full-size slide

  117. What? There’s
    nothing
    con
    fi
    dential in
    here!
    👱

    View full-size slide

  118. class AwardA < Grant
    @award_count = 0
    def self.award_count
    @award_count
    end


    def self.assign!
    @award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  119. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  120. class Grant

    MAX_GRANTS = 100
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  121. Let’s run the code!
    🕵

    View full-size slide

  122. jenny:rip_grant_program/ $

    View full-size slide

  123. jenny:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    100
    Awards left to assign:
    0
    SUCCESS: All awards assigned!

    View full-size slide

  124. Hey…check this
    out…
    🕵

    View full-size slide

  125. class Grant

    MAX_GRANTS = 100
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  126. class Grant

    MAX_GRANTS = 100
    @@award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  127. class Grant

    MAX_GRANTS = 100
    @@award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  128. Let’s run this code!
    🕵

    View full-size slide

  129. jenny:rip_grant_program/ $

    View full-size slide

  130. jenny:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    300
    Awards left to assign:
    -200
    ERROR: Maximum number of grants exceeded!

    View full-size slide

  131. Let’s go and
    fi
    nd
    Alex!
    👱

    View full-size slide

  132. He was trying to
    fi
    nd a
    quiet corner to take a
    personal call.
    🧑🦱

    View full-size slide

  133. Zoë, they almost
    caught me...
    🧔

    View full-size slide

  134. …even brought in a
    private investigator…
    🧔

    View full-size slide

  135. …faked some code for
    fun and to buy time…
    🧔

    View full-size slide

  136. …Jenny will be nosy so
    I
    fi
    xed the real code for
    now…
    🧔

    View full-size slide

  137. But don’t worry,
    honey…
    🧔

    View full-size slide

  138. …I’ll put the bug
    back in before
    the
    fi
    nal
    tomorrow!
    🧔

    View full-size slide

  139. CHAPTER FIVE

    View full-size slide

  140. 👩🦱
    🧔💘

    View full-size slide

  141. 👩🦱
    Zoë’s team

    View full-size slide

  142. 👩🦱
    Zoë’s team
    vs
    👱
    Jenny’s team

    View full-size slide

  143. 👩🦱
    Zoë’s team
    vs
    👱
    Jenny’s team
    for

    View full-size slide

  144. 👩🦱
    Zoë’s team
    vs
    👱
    Jenny’s team
    for
    💰💰💰

    View full-size slide

  145. 🧔
    My team’s idea
    =
    😴

    View full-size slide

  146. 🧔
    Zoë’s team’s idea
    =
    😍

    View full-size slide

  147. 🧔
    Zoë’s team’s idea
    =
    My idea! 😌

    View full-size slide

  148. 👩🦱
    Zoë’s team
    vs
    👱
    Jenny’s team

    View full-size slide

  149. 👩🦱
    Zoë’s team
    vs
    👱
    Jenny’s team
    🥇 🥈

    View full-size slide

  150. 👩🦱
    🧔💘

    View full-size slide

  151. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end

    View full-size slide

  152. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end

    View full-size slide

  153. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end
    🕵

    View full-size slide

  154. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end
    Those class
    variables look
    suspect…
    🕵

    View full-size slide

  155. …faked some code for
    fun and to buy time…
    🧔

    View full-size slide

  156. deebug:vanished_variable/ $

    View full-size slide

  157. deebug:vanished_variable/ $ pry
    [1] pry(main)> class Grant
    [1] pry(main)* @@type = “Grant”
    [1] pry(main)* def self.type
    [1] pry(main)* @@type
    [1] pry(main)* end
    end
    [1] pry(main)*
    => :type
    [2] pry(main)> Grant.type
    => “Grant”

    View full-size slide

  158. [2] pry(main)> Grant.type
    => “Grant”

    View full-size slide

  159. [2] pry(main)> Grant.type
    => “Grant”
    [3] pry(main)> class AwardA < Grant
    [3] pry(main)* @@type = “A”
    [3] pry(main)* def self.type
    [3] pry(main)* @@type
    [3] pry(main)* end
    end
    [3] pry(main)*
    => :type
    [4] pry(main)>

    View full-size slide

  160. [3] pry(main)* def self.type
    [3] pry(main)* @@type
    [3] pry(main)* end
    end
    [3] pry(main)*
    => :type
    [4] pry(main)>

    View full-size slide

  161. [3] pry(main)* def self.type
    [3] pry(main)* @@type
    [3] pry(main)* end
    end
    [3] pry(main)*
    => :type
    [5] pry(main)> Grant.type
    => “A”
    [4] pry(main)> AwardA.type
    => “A”

    View full-size slide

  162. class Grant @type = “Grant”

    View full-size slide

  163. class Grant
    class AwardA
    @type = “Grant”
    @type = “A”

    View full-size slide

  164. class Grant
    class AwardA
    @type = “Grant”
    @type = “A”
    inherits from

    View full-size slide

  165. @@type = “Grant”
    class Grant

    View full-size slide

  166. @@type = “Grant”
    @@type = “A”
    class Grant
    class AwardA

    View full-size slide

  167. @@type = “A”
    @@type = “A”
    class Grant
    class AwardA
    inherits from

    View full-size slide

  168. Does direction
    matter?
    🕵

    View full-size slide

  169. [6] pry(main)>

    View full-size slide

  170. [6] pry(main)>
    [7] pry(main)> Grant.superclass
    => Object
    [8] pry(main)> class Object
    [8] pry(main)* @@type = “Object”
    [8] pry(main)* def self.type
    [8] pry(main)* @@type
    [8] pry(main)* end
    end
    [8] pry(main)*
    => :type

    View full-size slide

  171. [8] pry(main)* def self.type
    [8] pry(main)* @@type
    [8] pry(main)* end
    end
    [8] pry(main)*
    => :type
    [9] pry(main)>

    View full-size slide

  172. [8] pry(main)* def self.type
    [8] pry(main)* @@type
    [8] pry(main)* end
    end
    [8] pry(main)*
    => :type
    [10] pry(main)>
    [9] pry(main)> Object.type
    => “Object”

    View full-size slide

  173. [8] pry(main)* def self.type
    [8] pry(main)* @@type
    [8] pry(main)* end
    end
    [8] pry(main)*
    => :type
    [10] pry(main)> Grant.type
    [9] pry(main)> Object.type
    => “Object”
    RuntimeError: class variable @@type of Grant is overtaken by Object
    from (pry):4:in `type'
    [11] pry(main)>

    View full-size slide

  174. [10] pry(main)> Grant.type
    [9] pry(main)> Object.type
    => “Object”
    RuntimeError: class variable @@type of Grant is overtaken by Object
    from (pry):4:in `type'
    [11] pry(main)>

    View full-size slide

  175. [10] pry(main)> Grant.type
    [9] pry(main)> Object.type
    => “Object”
    RuntimeError: class variable @@type of Grant is overtaken by Object
    from (pry):4:in `type'
    [11] pry(main)> AwardA.type
    RuntimeError: class variable @@type of Grant is overtaken by Object
    from (pry):11:in `type'
    [12] pry(main)>

    View full-size slide

  176. @@type = “A”
    @@type = “A”
    class Grant
    class AwardA
    inherits from

    View full-size slide

  177. @@type = “A”
    @@type = “A”
    class Grant
    class AwardA
    inherits from
    inherits from
    class Object

    View full-size slide

  178. @@type = “A”
    @@type = “A”
    class Grant
    class AwardA
    inherits from
    inherits from
    class Object @@type = “Object”

    View full-size slide

  179. class Grant
    class AwardA
    inherits from
    inherits from
    class Object @@type = “Object”
    @@type = RuntimeError
    @@type = RuntimeError

    View full-size slide

  180. I wonder how far
    up the inheritance
    chain this goes!
    🕵

    View full-size slide

  181. [12] pry(main)>

    View full-size slide

  182. [12] pry(main)>
    [13] pry(main)> Grant.ancestors
    => [Grant, Object, PP::ObjectMixin, Kernel, BasicObject]
    [14] pry(main)> class BasicObject
    [14] pry(main)* @@type = “Basic”
    [14] pry(main)* def self.type
    [14] pry(main)* @@type
    [14] pry(main)* end
    end
    [14] pry(main)*
    => :type
    [15] pry(main)>

    View full-size slide

  183. [14] pry(main)> class BasicObject
    [14] pry(main)* @@type = “Basic”
    [14] pry(main)* def self.type
    [14] pry(main)* @@type
    [14] pry(main)* end
    end
    [14] pry(main)*
    => :type
    [15] pry(main)>

    View full-size slide

  184. [14] pry(main)> class BasicObject
    [14] pry(main)* @@type = “Basic”
    [14] pry(main)* def self.type
    [14] pry(main)* @@type
    [14] pry(main)* end
    end
    [14] pry(main)*
    => :type
    [15] pry(main)> Grant.type
    RuntimeError: class variable @@type of Grant is overtaken by BasicObject
    from (pry):4:in `type'
    [16] pry(main)>

    View full-size slide

  185. Time for some good
    ol’ pen and paper!
    🕵

    View full-size slide

  186. RClass
    Class instance variables
    @type

    View full-size slide

  187. RClass
    Class instance variables
    @type
    Class variables
    @@type

    View full-size slide

  188. RClass
    Class variables
    @@award_count = 0
    : Grant

    View full-size slide

  189. RClass
    Class variables
    @@award_count = 0
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC

    View full-size slide

  190. RClass
    Class variables
    @@award_count = 0
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    class AwardA < Grant
    @@award_count = 0

    end

    View full-size slide

  191. 50.times do
    AwardA.assign!
    end
    assign_a.rb

    View full-size slide

  192. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  193. RClass
    Class variables
    @@award_count = 0
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    50.times do
    AwardA.assign!
    end

    View full-size slide

  194. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    50.times do
    AwardA.assign!
    end

    View full-size slide

  195. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    50.times do
    AwardA.assign!
    end

    View full-size slide

  196. class AwardA < Grant
    @@award_count = 0
    def self.award_count
    @@award_count
    end


    def self.assign!
    @@award_count += 1
    end
    end
    award_a.rb

    View full-size slide

  197. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 50

    View full-size slide

  198. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 50

    View full-size slide

  199. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 50
    AwardB.award_count = 50
    AwardC.award_count = 50

    View full-size slide

  200. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 50
    AwardB.award_count = 50
    AwardC.award_count = 50

    View full-size slide

  201. RClass
    Class variables
    @@award_count = 50
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    30.times do
    AwardB.assign!
    end

    View full-size slide

  202. RClass
    Class variables
    @@award_count = 80
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 80
    AwardB.award_count = 80
    AwardC.award_count = 80

    View full-size slide

  203. RClass
    Class variables
    @@award_count = 80
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 80
    AwardB.award_count = 80
    AwardC.award_count = 80

    View full-size slide

  204. RClass
    Class variables
    @@award_count = 80
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    20.times do
    AwardC.assign!
    end

    View full-size slide

  205. RClass
    Class variables
    @@award_count = 100
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 100
    AwardB.award_count = 100
    AwardC.award_count = 100

    View full-size slide

  206. RClass
    Class variables
    @@award_count = 100
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 100
    AwardB.award_count = 100
    AwardC.award_count = 100

    View full-size slide

  207. class Grant

    MAX_GRANTS = 100
    @@award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  208. class Grant

    MAX_GRANTS = 100
    @@award_count = 0
    def self.award_count
    AwardA.award_count +

    AwardB.award_count +

    AwardC.award_count
    end


    def self.awards_remaining
    MAX_GRANTS -
    self.award_count
    end
    end
    grant.rb

    View full-size slide

  209. RClass
    Class variables
    @@award_count = 100
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 100
    AwardB.award_count = 100
    AwardC.award_count = 100

    View full-size slide

  210. RClass
    Class variables
    @@award_count = 100
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 100
    AwardB.award_count = 100
    AwardC.award_count = 100

    View full-size slide

  211. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…

    View full-size slide

  212. alex:rip_grant_program/ $ ruby grant_awards.rb
    Awarding 50 grants of type A…
    Awarding 30 grants of type B…
    Awarding 20 grants of type C…
    Checking if prize redraw is needed…
    Total number of grants awarded so far…
    300
    Awards left to assign:
    -200
    ERROR: Maximum number of grants exceeded!

    View full-size slide

  213. I know just the
    person!
    🕵

    View full-size slide

  214. 👳
    Ellen
    • 45 years old

    View full-size slide

  215. 👳
    Ellen
    • 45 years old
    • Freelance developer

    View full-size slide

  216. 👳
    Ellen
    • 45 years old
    • Freelance developer
    • Ruby committer

    View full-size slide

  217. RClass
    Class variables
    @@award_count = 100
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC
    AwardA.award_count = 100
    AwardB.award_count = 100
    AwardC.award_count = 100

    View full-size slide

  218. 🕵
    Did I get it right??

    View full-size slide

  219. 👳
    Yes! Except for
    one small thing…

    View full-size slide

  220. RClass
    Class instance variables
    @type
    Class variables
    @@type

    View full-size slide

  221. RClass
    Class-level variables
    @type
    @@type

    View full-size slide

  222. 🕵
    Class variables only
    seem to cause a lot
    of trouble…

    View full-size slide

  223. 👳
    Application
    con
    fi
    guration!

    View full-size slide

  224. 🕵
    But does the
    everyday developer
    have to care about
    them?

    View full-size slide

  225. 👳
    Well…let me tell
    you a story…

    View full-size slide

  226. [14] pry(main)> class BasicObject
    [14] pry(main)* @@type = “Basic”
    [14] pry(main)* def self.type
    [14] pry(main)* @@type
    [14] pry(main)* end
    end
    [14] pry(main)*
    => :type
    [15] pry(main)>

    View full-size slide

  227. [14] pry(main)> class BasicObject
    [14] pry(main)* @@type = “Basic”
    [14] pry(main)* def self.type
    [14] pry(main)* @@type
    [14] pry(main)* end
    end
    [14] pry(main)*
    => :type
    [15] pry(main)> Grant.type
    RuntimeError: class variable @@type of Grant is overtaken by BasicObject
    from (pry):4:in `type'
    [16] pry(main)>

    View full-size slide

  228. Eileen M. Uchitelle
    @eileencodes

    View full-size slide

  229. Aaron Patterson
    @tenderlove
    Eileen M. Uchitelle
    @eileencodes

    View full-size slide

  230. RClass
    Class variables
    @@award_count = 0
    : Grant
    RClass: AwardB
    RClass: AwardA RClass: AwardC

    View full-size slide

  231. We should build a
    cache!
    We should build a
    cache!

    View full-size slide

  232. Grant
    AwardA
    AwardA.award_count
    @@award_count

    View full-size slide

  233. Grant
    AwardA
    AwardA.award_count
    @@award_count
    ActiveSupport Object PP::ObjectM
    @@award_count? @@award_count? @@award_co

    View full-size slide

  234. AwardA.award_count
    Grant
    AwardA
    @@award_count
    ActiveSupport Object PP::ObjectM
    @@award_count? @@award_count? @@award_co

    View full-size slide

  235. AwardA.award_count
    pport Object PP::ObjectMixin
    count? @@award_count? @@award_count?

    View full-size slide

  236. AwardA.award_count
    pport Object PP::ObjectMixin
    count? @@award_count? @@award_count?
    Kernel
    @@award_count?

    View full-size slide

  237. AwardA.award_count
    pport Object PP::ObjectMixin
    count? @@award_count? @@award_count?
    Kernel BasicObject
    @@award_count? @@award_count?

    View full-size slide

  238. Grant
    AwardA
    AwardA.award_count
    @@award_count
    ActiveSupport Object PP::ObjectM

    View full-size slide

  239. Grant
    AwardA
    AwardA.award_count
    @@award_count
    ActiveSupport Object PP::ObjectM
    CACHE

    View full-size slide

  240. Grant
    AwardA
    AwardA.award_count
    @@award_count
    ActiveSupport Object PP::ObjectM
    @@award_count? @@award_count? @@award_co
    CACHE Grant

    View full-size slide

  241. 👳
    Why did I tell you
    this story?

    View full-size slide

  242. Ruby is slow!
    🧑🦳

    View full-size slide

  243. Ruby is slow!
    🧑🦳
    Ruby doesn’t
    scale!
    🧑🌾

    View full-size slide

  244. Ruby is slow!
    🧑🦳
    Ruby doesn’t
    scale!
    🧑🌾
    Ruby is dying!
    👩🔧

    View full-size slide

  245. Understand Ruby

    View full-size slide

  246. Improve Ruby

    View full-size slide

  247. Ruby is slow!
    🧑🦳
    Ruby doesn’t
    scale!
    🧑🌾
    Ruby is dying!
    👩🔧

    View full-size slide

  248. Keep Ruby alive

    View full-size slide

  249. Alex was
    fi
    red from the RIP…

    View full-size slide

  250. The RIP Grant Program won the
    $500k prize and continues to run
    successfully, headed up by
    Jenny…

    View full-size slide

  251. The shady mastermind behind Ruby
    is still at large…

    View full-size slide