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
16

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
  2. None
  3. None
  4. None
  5. None
  6. None
  7. None
  8. None
  9. 3 million unique visitors per month

  10. 36 million pageviews per month

  11. 110 million requests per month

  12. None
  13. None
  14. None
  15. None
  16. None
  17. 👀

  18. None
  19. 🕵

  20. None
  21. None
  22. None
  23. 💰💰💰

  24. 💰💰💰

  25. Nadia Odunayo

  26. Nadia Odunayo

  27. Deirdre Bug

  28. Deirdre Bug

  29. Dee Bug

  30. CASE FILES

  31. CASE FILES #048

  32. CASE FILES #048 Vanished Variable

  33. CHAPTER ONE

  34. None
  35. None
  36. None
  37. None
  38. None
  39. None
  40. None
  41. None
  42. 📞

  43. 📞

  44. I know I’m the last person you want to hear

    from…
  45. …but I need your help!

  46. …but I need your help! 👱

  47. Jenny • 29 years old 👱

  48. Jenny • 29 years old • Ruby developer 👱

  49. Jenny • 29 years old • Ruby developer • Rails

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

    obsessed 👱 • Betrayed her best friend
  51. Ruby Institute of Professionals

  52. RIP Ruby Institute of Professionals

  53. Incubator RIP

  54. Incubator • Help Ruby’s image RIP

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

  56. Incubator • Help Ruby’s image • Startup ideas • $500k

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

    prize • Jenny’s team in fi nal two RIP
  58. We’re building a platform that assigns grants… 👱

  59. There are three different types of award… 👱

  60. Our demo simulates an example draw… 👱

  61. …but our code has a bug! 👱

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

  63. 🧔

  64. 😰 🧔

  65. We need you. 👱

  66. None
  67. None
  68. 🕵

  69. 💰💰💰

  70. 💰💰💰

  71. None
  72. CHAPTER TWO

  73. I don’t need help. 🧔

  74. But, Alex…! 👱

  75. None
  76. I’ll tell you what, Alex… 🕵

  77. None
  78. None
  79. …you’ll fi nd the bug quicker! 🕵

  80. Fine. 🧔

  81. 👱

  82. 💪 👱

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

  84. None
  85. None
  86. None
  87. 40 minutes later…

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

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

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

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

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

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

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

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

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

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

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

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

    @award_count += 1 end end award_c.rb class AwardC < Grant
  100. 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
  101. 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
  102. 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
  103. 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
  104. 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
  105. 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
  106. 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
  107. 50.times do AwardA.assign! end assign_a.rb

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

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

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

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

  112. 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
  113. 50.times do AwardA.assign! end

  114. 50.times do AwardA.assign! end

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

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

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

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

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

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

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

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

    do AwardC.assign! end + = 100 = MAX_GRANTS
  123. Following so far…? 🧔

  124. I got it. 🕵

  125. alex:rip_grant_program/ $

  126. 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!
  127. 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!
  128. None
  129. CHAPTER THREE

  130. 🕵

  131. @award_count

  132. class AwardA < Grant @award_count = 0 … end

  133. class AwardA < Grant @award_count = 0 … end class

    AwardB < Grant @award_count = 0 … end
  134. class AwardA < Grant @award_count = 0 … end class

    AwardB < Grant @award_count = 0 … end class AwardC < Grant @award_count = 0 … end
  135. 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
  136. What if each class were to have a differently-named class

    instance variable? 🕵
  137. Sure…we can try that. 🧔

  138. class AwardA < Grant @award_count = 0 def self.award_count @award_count

    end
 
 def self.assign! @award_count += 1 end end award_a.rb
  139. 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
  140. 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
  141. alex:rip_grant_program/ $

  142. 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!
  143. None
  144. None
  145. Alex! You’ll never guess who’s in the of fi ce!

    🧑🦱
  146. Matz! 🧑🦱

  147. None
  148. 🏃💨

  149. 🏃💨

  150. 🏃💨

  151. 🏃💨 💰💰💰 💰💰💰 💰💰💰

  152. 🕵

  153. $

  154. $ git status

  155. $

  156. $ git diff

  157. None
  158. +++ b/assign_c.rb @@ -0,0 +1,151 @@

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

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

  161. None
  162. class Grant @award_count = 300 def self.award_count @award_count end end

  163. What are you looking at? 🧔

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

  165. That’s from an old demo. 🧔

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

  167. 🧔

  168. 😳 🧔

  169. …you never do partial commits? 🕵

  170. 🧔

  171. 😳 🧔

  172. 🕵

  173. 😌 🕵

  174. 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
  175. None
  176. alex:rip_grant_program/ $

  177. 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!
  178. None
  179. CHAPTER FOUR

  180. Dee!! 👱

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

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

    👱
  183. 🕵 You mean class instance variables!

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

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

    🕵 You don’t mean class instance variables?
  186. @@award_count

  187. @award_count

  188. 👱

  189. 🤨 👱

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

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

  192. 🕵

  193. 🤨 🕵

  194. 🕵 😲

  195. class AwardA < Grant @award_count = 0 def self.award_count @award_count

    end
 
 def self.assign! @award_count += 1 end end award_a.rb
  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
  197. 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
  198. Let’s run the code! 🕵

  199. jenny:rip_grant_program/ $

  200. 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!
  201. Hey…check this out… 🕵

  202. None
  203. 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
  204. 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
  205. 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
  206. Let’s run this code! 🕵

  207. jenny:rip_grant_program/ $

  208. 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!
  209. None
  210. Let’s go and fi nd Alex! 👱

  211. He was trying to fi nd a quiet corner to

    take a personal call. 🧑🦱
  212. Zoë, they almost caught me... 🧔

  213. …even brought in a private investigator… 🧔

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

  215. …Jenny will be nosy so I fi xed the real

    code for now… 🧔
  216. But don’t worry, honey… 🧔

  217. …I’ll put the bug back in before the fi nal

    tomorrow! 🧔
  218. 🧔

  219. 😰 🧔

  220. CHAPTER FIVE

  221. So… 🕵

  222. 🧔

  223. 🧔💘

  224. 👩🦱 🧔💘

  225. 👩🦱 Zoë’s team

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

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

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

  229. 🧔

  230. 🧔 My team’s idea = 😴

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

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

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

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

  235. 👩🦱 🧔💘

  236. 🧔

  237. 😼 🧔

  238. class AwardA < Grant @@award_count = 0 def self.award_count @@award_count

    end
 
 def self.assign! @@award_count += 1 end end
  239. class AwardA < Grant @@award_count = 0 def self.award_count @@award_count

    end
 
 def self.assign! @@award_count += 1 end end
  240. class AwardA < Grant @@award_count = 0 def self.award_count @@award_count

    end
 
 def self.assign! @@award_count += 1 end end 🕵
  241. 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… 🕵
  242. …faked some code for fun and to buy time… 🧔

  243. None
  244. Yup. 👱

  245. Wow. 🕵

  246. None
  247. deebug:vanished_variable/ $

  248. 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”
  249. [2] pry(main)> Grant.type => “Grant”

  250. [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)>
  251. [3] pry(main)* def self.type [3] pry(main)* @@type [3] pry(main)* end

    end [3] pry(main)* => :type [4] pry(main)>
  252. [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”
  253. class Grant @type = “Grant”

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

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

    inherits from
  256. @@type = “Grant” class Grant

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

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

    inherits from
  259. Does direction matter? 🕵

  260. [6] pry(main)>

  261. [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
  262. [8] pry(main)* def self.type [8] pry(main)* @@type [8] pry(main)* end

    end [8] pry(main)* => :type [9] pry(main)>
  263. [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”
  264. [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)>
  265. [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)>
  266. [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)>
  267. @@type = “A” @@type = “A” class Grant class AwardA

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

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

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

    @@type = “Object” @@type = RuntimeError @@type = RuntimeError
  271. I wonder how far up the inheritance chain this goes!

    🕵
  272. [12] pry(main)>

  273. [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)>
  274. [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)>
  275. [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)>
  276. Time for some good ol’ pen and paper! 🕵

  277. RClass

  278. RClass Class instance variables @type

  279. RClass Class instance variables @type Class variables @@type

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

  281. RClass Class variables @@award_count = 0 : Grant RClass: AwardB

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

    RClass: AwardA RClass: AwardC class AwardA < Grant @@award_count = 0 … end
  283. 50.times do AwardA.assign! end assign_a.rb

  284. class AwardA < Grant @@award_count = 0 def self.award_count @@award_count

    end
 
 def self.assign! @@award_count += 1 end end award_a.rb
  285. RClass Class variables @@award_count = 0 : Grant RClass: AwardB

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

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

    RClass: AwardA RClass: AwardC 50.times do AwardA.assign! end
  288. class AwardA < Grant @@award_count = 0 def self.award_count @@award_count

    end
 
 def self.assign! @@award_count += 1 end end award_a.rb
  289. RClass Class variables @@award_count = 50 : Grant RClass: AwardB

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

    RClass: AwardA RClass: AwardC AwardA.award_count = 50
  291. 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
  292. 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
  293. RClass Class variables @@award_count = 50 : Grant RClass: AwardB

    RClass: AwardA RClass: AwardC 30.times do AwardB.assign! end
  294. 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
  295. 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
  296. RClass Class variables @@award_count = 80 : Grant RClass: AwardB

    RClass: AwardA RClass: AwardC 20.times do AwardC.assign! end
  297. 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
  298. 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
  299. 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
  300. 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
  301. 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
  302. 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
  303. 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…
  304. 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!
  305. 🕵

  306. 😌 🕵

  307. I know just the person! 🕵

  308. CHAPTER SIX

  309. 👳

  310. 👳 Ellen • 45 years old

  311. 👳 Ellen • 45 years old • Freelance developer

  312. 👳 Ellen • 45 years old • Freelance developer •

    Ruby committer
  313. 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
  314. 🕵 Did I get it right??

  315. 👳 Yes! Except for one small thing…

  316. RClass Class instance variables @type Class variables @@type

  317. RClass

  318. RClass

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

  320. 🕵 Class variables only seem to cause a lot of

    trouble…
  321. 👳 Application con fi guration!

  322. None
  323. 🕵 But does the everyday developer have to care about

    them?
  324. 👳 Well…let me tell you a story…

  325. [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)>
  326. [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)>
  327. None
  328. Eileen M. Uchitelle @eileencodes

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

  330. RClass Class variables @@award_count = 0 : Grant RClass: AwardB

    RClass: AwardA RClass: AwardC
  331. None
  332. None
  333. None
  334. None
  335. We should build a cache! We should build a cache!

  336. None
  337. Grant AwardA AwardA.award_count @@award_count

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

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

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

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

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

    @@award_count?
  343. Grant AwardA AwardA.award_count @@award_count ActiveSupport Object PP::ObjectM

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

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

    CACHE Grant
  346. None
  347. None
  348. None
  349. 👳 Why did I tell you this story?

  350. Ruby is slow! 🧑🦳

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

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

    dying! 👩🔧
  353. None
  354. None
  355. Learn Ruby

  356. Understand Ruby

  357. Improve Ruby

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

    dying! 👩🔧
  359. None
  360. Keep Ruby alive

  361. 🕵

  362. 🤩 🕵

  363. EPILOGUE

  364. None
  365. Alex was fi red from the RIP…

  366. None
  367. The RIP Grant Program won the $500k prize and continues

    to run successfully, headed up by Jenny…
  368. None
  369. The shady mastermind behind Ruby is still at large…

  370. THE END

  371. THE END?