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

Nothing is Something (RailsConf)

Nothing is Something (RailsConf)

Our code is full of hidden assumptions, things that seem like nothing, secrets that we did not name and thus cannot see.

These secrets represent missing concepts and this talk shows you how to expose those concepts with code that is easy to understand, change and extend.

Being explicit about hidden ideas makes your code simpler, your apps clearer and your life better. Even very small ideas matter. Everything, even nothing, is something.

Sandi Metz

April 16, 2015
Tweet

More Decks by Sandi Metz

Other Decks in Programming

Transcript

  1. Jan 2015
    @sandimetz
    Sandi Metz
    Nothing
    is
    Something

    View Slide

  2. Jan 2015
    @sandimetz

    View Slide

  3. Jan 2015
    @sandimetz

    View Slide

  4. Jan 2015
    @sandimetz
    Smalltalk Infected

    View Slide

  5. Jan 2015
    @sandimetz
    1.to_s  

    View Slide

  6. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"

    View Slide

  7. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)

    View Slide

  8. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"

    View Slide

  9. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"

    View Slide

  10. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"
    1  +  1

    View Slide

  11. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"
    1  +  1  
    =>  2

    View Slide

  12. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"
    1  +  1  
    =>  2  
    1.send(:+,  1)

    View Slide

  13. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  14. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  15. Jan 2015
    @sandimetz
    1.class
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  16. Jan 2015
    @sandimetz
    1.class  
    =>  Fixnum
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  17. Jan 2015
    @sandimetz
    Fixnum.instance_methods(false)  
    =>  [  
     :to_s,  
     :+,  
     :-­‐,  
     :*,  
     :/,  
     :==,  
     :%,  
     :modulo,  #  etc
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  18. Jan 2015
    @sandimetz
    Fixnum.instance_methods(false)  
    =>  [  
     :to_s,  
     :+,  
     :-­‐,  
     :*,  
     :/,  
     :==,  
     :%,  
     :modulo,  #  etc
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  19. Jan 2015
    @sandimetz
    Fixnum.instance_methods(false)  
    =>  [  
     :to_s,  
     :+,  
     :-­‐,  
     :*,  
     :/,  
     :==,  
     :%,  
     :modulo,  #  etc
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  20. Jan 2015
    @sandimetz
    Fixnum.instance_methods(false)  
    =>  [  
     :to_s,  
     :+,  
     :-­‐,  
     :*,  
     :/,  
     :==,  
     :%,  
     :modulo,  #  etc
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2

    View Slide

  21. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2
    1  ==  1

    View Slide

  22. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2
    1  ==  1  
    =>  true

    View Slide

  23. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true

    View Slide

  24. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true
    true.class

    View Slide

  25. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true
    true.class  
    =>  TrueClass

    View Slide

  26. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true  
    true.class  
    =>  TrueClass

    View Slide

  27. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true  
    true.class  
    =>  TrueClass
    TrueClass.instance_methods(false)  
    =>  [  
     :to_s,    
     :inspect,    
     :&,    
     :|,    
     :^,    
     :pretty_print_cycle,    
     :pretty_print]  

    View Slide

  28. Jan 2015
    @sandimetz
    1.to_s  
    =>  "1"  
    1.send(:to_s)  
    =>  "1"  
    1  +  1  
    =>  2  
    1.send(:+,  1)  
    =>  2  
    1  ==  1  
    =>  true  
    true.class  
    =>  TrueClass
    TrueClass.instance_methods(false)  
    =>  [  
     :to_s,    
     :inspect,    
     :&,    
     :|,    
     :^,    
     :pretty_print_cycle,    
     :pretty_print]  

    View Slide

  29. Jan 2015
    @sandimetz
    ‘Special’ syntax for booleans

    View Slide

  30. Jan 2015
    @sandimetz
    Smalltalk keywords
    true,  false,  nil,  self,  super,  thisContext

    View Slide

  31. Jan 2015
    @sandimetz
    Smalltalk keywords
    true,  false,  nil,  self,  super,  thisContext  
    Ruby keywords
    alias  and  BEGIN  begin  break  case  class  def  defined?  do  
    else  elsif  END  end  ensure  false  for  if  in  module  next  nil  
    not  or  redo  rescue  retry  return  self  super  then  true  
    undef  unless  until  when  while  yield

    View Slide

  32. Jan 2015
    @sandimetz
    Smalltalk keywords
    true,  false,  nil,  self,  super,  thisContext  
    Ruby keywords
    alias  and  BEGIN  begin  break  case  class  def  defined?  do  
    else  elsif  END  end  ensure  false  for  if  in  module  next  nil  
    not  or  redo  rescue  retry  return  self  super  then  true  
    undef  unless  until  when  while  yield

    View Slide

  33. Jan 2015
    @sandimetz
    if  (1  ==  1)  
       'is  true'  
    else  
       'is  false'  
    end

    View Slide

  34. Jan 2015
    @sandimetz
    if  (1  ==  1)  
       'is  true'  
    else  
       'is  false'  
    end
    true

    View Slide

  35. Jan 2015
    @sandimetz
    if  (1  ==  1)  
       'is  true'  
    else  
       'is  false'  
    end  
    =>  'is  true'
    true

    View Slide

  36. Jan 2015
    @sandimetz
    if  (1  ==  1)  
       code  to  eval  when  ‘true’  
    else  
       code  to  eval  when  ‘false’  
    end
    true

    View Slide

  37. Jan 2015
    @sandimetz
    if  (  truthy  )  
       code  to  eval  when  ‘truthy’  
    else  
       code  to  eval  when  ‘falsey’  
    end

    View Slide

  38. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       code  to  do  some  stuff  
    else  
       code  to  do  some  other  stuff  
    end

    View Slide

  39. Jan 2015
    @sandimetz
    I just want to
    send a message
    to an object

    View Slide

  40. Jan 2015
    @sandimetz

    View Slide

  41. Jan 2015
    @sandimetz
    if

    View Slide

  42. Jan 2015
    @sandimetz
    if
    is an enabler

    View Slide

  43. Jan 2015
    @sandimetz
    ‘Message sending’ syntax
    for
    TrueClass / FalseClass

    View Slide

  44. Jan 2015
    @sandimetz
    class  TrueClass  
    end

    View Slide

  45. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
       end  
    end

    View Slide

  46. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
    end

    View Slide

  47. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end

    View Slide

  48. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  49. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  50. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  51. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  52. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  53. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  54. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  55. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}

    View Slide

  56. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}

    View Slide

  57. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}
    true

    View Slide

  58. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"} class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       #  …  
    end
    true

    View Slide

  59. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"} class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       #  …  
    end

    View Slide

  60. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"} class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       #  …  
    end

    View Slide

  61. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       #  …  
    end

    View Slide

  62. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       #  …  
    end

    View Slide

  63. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end

    View Slide

  64. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end

    View Slide

  65. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}

    View Slide

  66. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}

    View Slide

  67. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}
    false

    View Slide

  68. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}
    false
    class  FalseClass
       def  if_true  
           self  
       end  
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  69. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}
    class  FalseClass
       def  if_true  
           self  
       end  
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  70. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}  
    #  block  is  ignored
    class  FalseClass
       def  if_true  
           self  
       end  
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  71. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_false  {puts  "evaluated  block"}
    class  FalseClass
       def  if_true  
           self  
       end  
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  72. Jan 2015
    @sandimetz
    (1  ==  1).if_true  {puts  "evaluated  block"}  
    "evaluated  block"  
    (1  ==  1).if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_true  {puts  "evaluated  block"}  
    #  block  is  ignored  
    (1  ==  2).if_false  {puts  "evaluated  block"}  
    "evaluated  block"
    class  FalseClass
       def  if_true  
           self  
       end  
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  73. Jan 2015
    @sandimetz
    ‘Message sending’ syntax
    for
    truthy/falsey

    View Slide

  74. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  75. Jan 2015
    @sandimetz
    class  TrueClass  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  76. Jan 2015
    @sandimetz
    class  Object  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  77. Jan 2015
    @sandimetz
    class  Object  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end
    class  NilClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end

    View Slide

  78. Jan 2015
    @sandimetz
    class  Object  
       def  if_true  
           yield  
           self  
       end  
       def  if_false  
           self  
       end  
    end
    class  FalseClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end
    class  NilClass  
       def  if_true  
           self  
       end  
         
       def  if_false  
           yield  
           self  
       end  
    end
    * Shamelessly swiped from
    http://yehudakatz.com/2009/10/04/emulating-smalltalks-conditionals-in-ruby/

    View Slide

  79. Jan 2015
    @sandimetz
       (1  ==  1).if_true    {puts  "evaluated  block"}

    View Slide

  80. Jan 2015
    @sandimetz

    View Slide

  81. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}

    View Slide

  82. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}
    "evaluated  block"

    View Slide

  83. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}

    View Slide

  84. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}  
    #  block  is  ignored

    View Slide

  85. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_true                  {puts  "evaluated  block"}

    View Slide

  86. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_true                  {puts  "evaluated  block"}  
    #  block  is  ignored

    View Slide

  87. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_true                  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_false                {puts  "evaluated  block"}

    View Slide

  88. Jan 2015
    @sandimetz
    "anything".if_true    {puts  "evaluated  block"}  
    "evaluated  block"  
    "anything".if_false  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_true                  {puts  "evaluated  block"}  
    #  block  is  ignored  
    nil.if_false                {puts  "evaluated  block"}  
    "evaluated  block"

    View Slide

  89. Jan 2015
    @sandimetz
    if  (1  ==  1)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  true'

    View Slide

  90. Jan 2015
    @sandimetz
    (1  ==  1).  
       if_true  {puts  'is  true'}.  
       if_false  {puts  'is  false’}  
    =>  'is  true'
    if  (1  ==  1)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  true'

    View Slide

  91. Jan 2015
    @sandimetz
    if  (1  ==  2)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  false'
    (1  ==  1).  
       if_true  {puts  'is  true'}.  
       if_false  {puts  'is  false’}  
    =>  'is  true'
    if  (1  ==  1)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  true'

    View Slide

  92. Jan 2015
    @sandimetz
    if  (1  ==  2)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  false'
    (1  ==  1).  
       if_true  {puts  'is  true'}.  
       if_false  {puts  'is  false’}  
    =>  'is  true'
    if  (1  ==  1)  
       puts  'is  true'  
    else  
       puts  'is  false'  
    end  
    =>  'is  true'
    (1  ==  2).  
       if_true  {puts  'is  true'}.  
       if_false  {puts  'is  false’}  
    =>  'is  false'

    View Slide

  93. Jan 2015
    @sandimetz
    I don't want to change Ruby

    View Slide

  94. Jan 2015
    @sandimetz
    I want to change you

    View Slide

  95. Jan 2015
    @sandimetz
    What if there were no 'if' ?

    View Slide

  96. Jan 2015
    @sandimetz
    Smalltalk Infected

    View Slide

  97. Jan 2015
    @sandimetz
    Smalltalk Infected

    View Slide

  98. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse

    View Slide

  99. Jan 2015
    @sandimetz
    Animal.find('pig')  
    =>  #

    View Slide

  100. Jan 2015
    @sandimetz
    Animal.find('pig')  
    =>  #  
    Animal.find('')  
    =>  nil

    View Slide

  101. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']

    View Slide

  102. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}

    View Slide

  103. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]

    View Slide

  104. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.name}  
    =>  'pig'  
         NoMethodError:  undefined  method  `name'  for  nil:NilClass

    View Slide

  105. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.name}  
    =>  'pig'  
         NoMethodError:  undefined  method  `name'  for  nil:NilClass

    View Slide

  106. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.name}  
    =>  'pig'  
         NoMethodError:  undefined  method  `name'  for  nil:NilClass

    View Slide

  107. Jan 2015
    @sandimetz
    Sometimes nil is nothing

    View Slide

  108. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]

    View Slide

  109. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.compact  
    =>  [#,    
           #]

    View Slide

  110. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.compact  
    =>  [#,    
             #]  
    animals.each  {|animal|puts  animal.name}  
    =>  'pig'    
         'sheep'

    View Slide

  111. Jan 2015
    @sandimetz

    View Slide

  112. Jan 2015
    @sandimetz
    But if you send it a message

    View Slide

  113. Jan 2015
    @sandimetz
    But if you send it a message
    nil is something

    View Slide

  114. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.name}  
    =>  'pig'  
         NoMethodError:  undefined  method  `name'  for  nil:NilClass

    View Slide

  115. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.name}  
    =>  'pig'  
         NoMethodError:  undefined  method  `name'  for  nil:NilClass

    View Slide

  116. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  117. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  118. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  119. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  120. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  121. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.nil?  ?  'no  animal'  :  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  122. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  123. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  124. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  125. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  126. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  127. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|  
       puts  animal  &&  animal.name  }  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  128. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.try(:name)}  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  129. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.try(:name)}  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  130. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.try(:name)}  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  131. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
             nil,    
             #]  
    animals.each  {|animal|    
       puts  animal.try(:name)}  
    =>  'pig'    
         empty  string  
         'sheep'

    View Slide

  132. Jan 2015
    @sandimetz
    puts  animal.try(:name)  
    puts  animal.nil?  ?  ''  :  animal.name  
    puts  animal  ==  nil  ?  ''  :  animal.name  
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name

    View Slide

  133. Jan 2015
    @sandimetz
    puts  animal.try(:name)  
    puts  animal.nil?  ?  ''  :  animal.name  
    puts  animal  ==  nil  ?  ''  :  animal.name  
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name

    View Slide

  134. Jan 2015
    @sandimetz
    puts  animal.try(:name)  
    puts  animal.nil?  ?  ''  :  animal.name  
    puts  animal  ==  nil  ?  ''  :  animal.name  
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name

    View Slide

  135. Jan 2015
    @sandimetz
    puts  animal.try(:name)  
    puts  animal.nil?  ?  ''  :  animal.name  
    puts  animal  ==  nil  ?  ''  :  animal.name  
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name

    View Slide

  136. Jan 2015
    @sandimetz
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name  
    if  animal.is_a?(NilClass)  
       puts  ''  
    else  
       puts  animal.name  
    end

    View Slide

  137. Jan 2015
    @sandimetz
    puts  animal.is_a?(NilClass)  ?  ''  :  animal.name  
    if  animal.is_a?(NilClass)  
       puts  ''  
    else  
       puts  animal.name  
    end

    View Slide

  138. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  ''  
    else  
       puts  animal.name  
    end

    View Slide

  139. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  ''  
    else  
       puts  animal.name  
    end

    View Slide

  140. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  ''  
    else  
       puts  animal.name  
    end

    View Slide

  141. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       code  to  do  some  stuff  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  142. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       code  to  do  some  stuff  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  143. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       code  to  do  some  stuff  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  144. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       I'll  supply  the  behavior  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  145. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       I'll  supply  the  behavior  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  146. Jan 2015
    @sandimetz
    if  (some  object  whose  type  I  know)  
       I'll  supply  the  behavior  
    else  
       code  to  do  some  other  stuff  
    end
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  147. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end
    if  (some  object  whose  type  I  know)  
       I'll  supply  the  behavior  
    else  
       I'll  send  a  message  
    end

    View Slide

  148. Jan 2015
    @sandimetz

    View Slide

  149. Jan 2015
    @sandimetz
    conditions

    View Slide

  150. Jan 2015
    @sandimetz
    conditions
    breed

    View Slide

  151. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name

    View Slide

  152. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name

    View Slide

  153. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name

    View Slide

  154. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name

    View Slide

  155. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name
    'no  animal'

    View Slide

  156. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name
    'no  animal'
    'no  animal'

    View Slide

  157. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name
    'no  animal'
    'no  animal'
    'no  animal'

    View Slide

  158. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name
    'no  animal'
    'no  animal'
    'no  animal'
    'no  animal'

    View Slide

  159. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    ind(id)  
    'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
    animal  =  Animal.find(id)  
    animal.nil?  ?  'no  animal'  :  animal.name
     Animal.find(id)  
     ?  'no  animal'  :  animal.name
    find(id)  
    animal'  :  animal.name
    d)  
    imal'  :  animal.name
    'no  animal'
    'no  animal'
    'no  animal'
    'no  animal'
    'no  animal'  
    !!!!

    View Slide

  160. Jan 2015
    @sandimetz
    Change?

    View Slide

  161. Jan 2015
    @sandimetz
    Shotgun
    Surgery

    View Slide

  162. Jan 2015
    @sandimetz
    Shotgun
    Surgery

    View Slide

  163. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse

    View Slide

  164. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse
    Message Centric

    View Slide

  165. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end
    if  (some  object  whose  type  I  know)  
       I'll  supply  the  behavior  
    else  
       I'll  send  a  message  
    end

    View Slide

  166. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  167. Jan 2015
    @sandimetz
    if  animal.is_a?(NilClass)  
       puts  'no  animal'  
    else  
       puts  animal.name  
    end

    View Slide

  168. Jan 2015
    @sandimetz
    class  Animal  
       def  name  
         ...  
       end  
    end

    View Slide

  169. Jan 2015
    @sandimetz
    class  Animal  
       def  name  
         ...  
       end  
    end  
    class  Nil  
       #  does  not  understand  name  
    end  

    View Slide

  170. Jan 2015
    @sandimetz
    class  Animal  
       def  name  
         ...  
       end  
    end  
    class  ???  
       def  name  
           'no  animal'  
       end  
    end

    View Slide

  171. Jan 2015
    @sandimetz
    class  Animal  
       def  name  
         ...  
       end  
    end  
    class  MissingAnimal  
       def  name  
           'no  animal'  
       end  
    end

    View Slide

  172. Jan 2015
    @sandimetz
    Prefer knowing an object
    to duplicating behavior

    View Slide

  173. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)}  
    =>  [#,    
           nil,    
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  174. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,    
           nil,    
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  175. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,    
           nil,    
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  176. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,    
           nil,    
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  177. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  178. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }
    added dependency

    View Slide

  179. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  180. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }
    still have the condition

    View Slide

  181. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }
    but no longer
    own the behavior

    View Slide

  182. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
       if  animal.is_a?(NilClass)  
           puts  'no  animal'  
       else  
           puts  animal.name  
       end  
    }

    View Slide

  183. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
           puts  animal.name  
    }

    View Slide

  184. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  
         puts  animal.name  
    }

    View Slide

  185. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name}

    View Slide

  186. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  187. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  188. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  189. Jan 2015
    @sandimetz
    class  Animal  
       def  name  
         ...  
       end  
    end  
    class  MissingAnimal  
       def  name  
           'no  animal'  
       end  
    end

    View Slide

  190. Jan 2015
    @sandimetz

    View Slide

  191. Jan 2015
    @sandimetz
    Null Object Pattern

    View Slide

  192. Jan 2015
    @sandimetz
    Null Object Pattern
    'Active Nothing'

    View Slide

  193. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    animals.each  {|animal|  puts  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'

    View Slide

  194. Jan 2015
    @sandimetz
    ids  =  ['pig',  '',  'sheep']  
    animals  =  ids.map  {|id|  Animal.find(id)  ||  MissingAnimal.new}  
    animals.each  {|animal|  puts  animal.name}  
    =>  'pig'    
         'no  animal'  
         'sheep'
    dependency

    View Slide

  195. Jan 2015
    @sandimetz
    Prefer knowing an object
    to duplicating behavior

    View Slide

  196. Jan 2015
    @sandimetz
    Prefer knowing
    few objects

    View Slide

  197. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name

    View Slide

  198. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name

    View Slide

  199. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  

    View Slide

  200. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  

    View Slide

  201. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  
    MissingAnimal

    View Slide

  202. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  
    MissingAnimal
    MissingAnimal

    View Slide

  203. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  
    MissingAnimal
    MissingAnimal
    MissingAnimal

    View Slide

  204. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  
    MissingAnimal
    MissingAnimal
    MissingAnimal
    MissingAnimal

    View Slide

  205. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find
     ||  MissingAnimal.new  
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    animal  =  Animal.find(id)  ||  MissingAnimal.new  
    animal.name
    al.find(id)  ||  MissingAnimal.new  
    )  ||  MissingAnimal.new  
    issingAnimal.new  
    MissingAnimal
    MissingAnimal
    MissingAnimal
    MissingAnimal
    MissingAnimal  
    ???

    View Slide

  206. Jan 2015
    @sandimetz
    class  Animal  
       def  self.find(id)  
           #  nil  or  an  Animal  
       end  
           #  …  
    end

    View Slide

  207. Jan 2015
    @sandimetz
    class  Animal  
    def  self.find

    View Slide

  208. Jan 2015
    @sandimetz
    class  GuaranteedAnimal  
    def  self.find
    class  Animal  
    def  self.find

    View Slide

  209. Jan 2015
    @sandimetz
    class  GuaranteedAnimal  
    def  self.find
    class  Animal  
    def  self.find
    class  GuaranteedAnimal  
       def  self.find(id)  
           Animal.find(id)  ||  MissingAnimal.new  
       end  
    end

    View Slide

  210. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|Animal.find(id)||MissingAnimal.new}

    View Slide

  211. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|Animal.find(id)||MissingAnimal.new}

    View Slide

  212. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|  
    GuaranteedAnimal.find(id)}  
    =>  [#,  
           #,  
           #]

    View Slide

  213. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|  
    GuaranteedAnimal.find(id)}  
    =>  [#,  
           #,  
           #]

    View Slide

  214. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|  
    GuaranteedAnimal.find(id)}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name  }  
    =>  'pig'  
         'no  animal'  
         'sheep'  

    View Slide

  215. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|  
    GuaranteedAnimal.find(id)}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name  }  
    =>  'pig'  
         'no  animal'  
         'sheep'  

    View Slide

  216. Jan 2015
    @sandimetz
    animals  =  ids.map  {|id|  
    GuaranteedAnimal.find(id)}  
    =>  [#,  
           #,  
           #]  
    animals.each  {|animal|  puts  animal.name  }  
    =>  'pig'  
         'no  animal'  
         'sheep'  

    View Slide

  217. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse
    Message Centric

    View Slide

  218. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse
    Message Centric
    Abstraction Seeking

    View Slide

  219. Jan 2015
    @sandimetz
       'This  is  the  house  that  Jack  built.'
    1

    View Slide

  220. Jan 2015
    @sandimetz
       'This  is  the  house  that  Jack  built.'  
       'This  is  the  malt  that  lay  in    
                         the  house  that  Jack  built.'
    1
    2

    View Slide

  221. Jan 2015
    @sandimetz
       'This  is  the  house  that  Jack  built.'  
       'This  is  the  malt  that  lay  in    
                         the  house  that  Jack  built.'  
       'This  is  the  rat  that  ate    
                         the  malt  that  lay  in    
                         the  house  that  Jack  built.'
    1
    2
    3

    View Slide

  222. Jan 2015
    @sandimetz
       'This  is  the  house  that  Jack  built.'  
       'This  is  the  malt  that  lay  in    
                         the  house  that  Jack  built.'  
       'This  is  the  rat  that  ate    
                         the  malt  that  lay  in    
                         the  house  that  Jack  built.'
       'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  
                         the  farmer  sowing  his  corn  that  kept  
                         the  rooster  that  crowed  in  the  morn  that  woke  
                         the  priest  all  shaven  and  shorn  that  married  
                         the  man  all  tattered  and  torn  that  kissed  
                         the  maiden  all  forlorn  that  milked  
                         the  cow  with  the  crumpled  horn  that  tossed  
                         the  dog  that  worried  
                         the  cat  that  killed    
                         the  rat  that  ate    
                         the  malt  that  lay  in    
                         the  house  that  Jack  built.'  
    12

    View Slide

  223. Jan 2015
    @sandimetz
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built'  ]  

    View Slide

  224. Jan 2015
    @sandimetz
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  

    View Slide

  225. Jan 2015
    @sandimetz
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  

    View Slide

  226. Jan 2015
    @sandimetz
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  

    View Slide

  227. Jan 2015
    @sandimetz
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    data.last(3)  
    =>  ['the  rat  that  ate',  
           'the  malt  that  lay  in',  
           'the  house  that  Jack  built']  

    View Slide

  228. Jan 2015
    @sandimetz
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  

    View Slide

  229. Jan 2015
    @sandimetz
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  230. Jan 2015
    @sandimetz
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  231. Jan 2015
    @sandimetz
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  232. Jan 2015
    @sandimetz
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  233. Jan 2015
    @sandimetz
       def  recite  
           (1..data.length).map  {|i|  line(i)}.join("\n")  
       end  
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  234. Jan 2015
    @sandimetz
       def  recite  
           (1..data.length).map  {|i|  line(i)}.join("\n")  
       end  
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  

    View Slide

  235. Jan 2015
    @sandimetz
    class  House  
       def  recite  
           (1..data.length).map  {|i|  line(i)}.join("\n")  
       end  
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  236. Jan 2015
    @sandimetz

    View Slide

  237. Jan 2015
    @sandimetz
    puts  House.new.line(1)
    =>  'This  is  the  house  that  Jack  built.'

    View Slide

  238. Jan 2015
    @sandimetz
    puts  House.new.line(1)
    =>  'This  is  the  house  that  Jack  built.'
    puts  House.new.line(2)
    =>  'This  is  the  malt  that  lay  in  the  house  that  Jack  built.'

    View Slide

  239. Jan 2015
    @sandimetz
    puts  House.new.line(1)
    =>  'This  is  the  house  that  Jack  built.'
    puts  House.new.line(2)
    =>  'This  is  the  malt  that  lay  in  the  house  that  Jack  built.'
    puts  House.new.line(3)
    =>  'This  is  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'

    View Slide

  240. Jan 2015
    @sandimetz
    puts  House.new.line(1)
    =>  'This  is  the  house  that  Jack  built.'
    puts  House.new.line(2)
    =>  'This  is  the  malt  that  lay  in  the  house  that  Jack  built.'
    puts  House.new.line(3)
    =>  'This  is  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    puts  House.new.line(12)
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  
    shaven  and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  
    all  forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  
    worried  the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  
    built.'

    View Slide

  241. Jan 2015
    @sandimetz
    puts  House.new.line(1)
    =>  'This  is  the  house  that  Jack  built.'
    puts  House.new.line(2)
    =>  'This  is  the  malt  that  lay  in  the  house  that  Jack  built.'
    puts  House.new.line(3)
    =>  'This  is  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    puts  House.new.line(12)
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  
    shaven  and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  
    all  forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  
    worried  the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  
    built.'
    puts  House.new.recite
    =>  
    'This  is  the  house  that  Jack  built.'
    'This  is  the  malt  that  lay  in  the  house  that  Jack  built.'
    'This  is  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    etc

    View Slide

  242. Jan 2015
    @sandimetz

    View Slide

  243. Jan 2015
    @sandimetz
    New Feature Request:

    View Slide

  244. Jan 2015
    @sandimetz
    New Feature Request:
    RandomHouse

    View Slide

  245. Jan 2015
    @sandimetz
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built'  ]  

    View Slide

  246. Jan 2015
    @sandimetz
           [  'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  dog  that  worried',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  malt  that  lay  in',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  house  that  Jack  built',  
               'the  cat  that  killed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  rat  that  ate']

    View Slide

  247. Jan 2015
    @sandimetz
           [  'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  dog  that  worried',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  malt  that  lay  in',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  house  that  Jack  built',  
               'the  cat  that  killed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  rat  that  ate']

    View Slide

  248. Jan 2015
    @sandimetz
           [  'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  dog  that  worried',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  malt  that  lay  in',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  house  that  Jack  built',  
               'the  cat  that  killed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  rat  that  ate']

    View Slide

  249. Jan 2015
    @sandimetz
           [  'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  dog  that  worried',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  malt  that  lay  in',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  house  that  Jack  built',  
               'the  cat  that  killed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  rat  that  ate']

    View Slide

  250. Jan 2015
    @sandimetz
       'This  is  the  rat  that  ate.'
    1

    View Slide

  251. Jan 2015
    @sandimetz
       'This  is  the  rat  that  ate.'  
       'This  is  the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'
    1
    2

    View Slide

  252. Jan 2015
    @sandimetz
       'This  is  the  rat  that  ate.'  
       'This  is  the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
       'This  is  the  cat  that  killed  
                         the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
    1
    2
    3

    View Slide

  253. Jan 2015
    @sandimetz
       'This  is  the  rat  that  ate.'  
       'This  is  the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
       'This  is  the  cat  that  killed  
                         the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
       'This  is  the  rooster  that  crowed  in  the  morn  that  woke    
                         the  farmer  sowing  his  corn  that  kept    
                         the  dog  that  worried    
                         the  priest  all  shaven  and  shorn  that  married    
                         the  man  all  tattered  and  torn  that  kissed    
                         the  horse  and  the  hound  and  the  horn  that  belonged  to    
                         the  malt  that  lay  in    
                         the  cow  with  the  crumpled  horn  that  tossed    
                         the  house  that  Jack  built    
                         the  cat  that  killed    
                         the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'
    12

    View Slide

  254. Jan 2015
    @sandimetz
       'This  is  the  rat  that  ate.'  
       'This  is  the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
       'This  is  the  cat  that  killed  
                         the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'  
       'This  is  the  rooster  that  crowed  in  the  morn  that  woke    
                         the  farmer  sowing  his  corn  that  kept    
                         the  dog  that  worried    
                         the  priest  all  shaven  and  shorn  that  married    
                         the  man  all  tattered  and  torn  that  kissed    
                         the  horse  and  the  hound  and  the  horn  that  belonged  to    
                         the  malt  that  lay  in    
                         the  cow  with  the  crumpled  horn  that  tossed    
                         the  house  that  Jack  built    
                         the  cat  that  killed    
                         the  maiden  all  forlorn  that  milked    
                         the  rat  that  ate.'
    12

    View Slide

  255. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  256. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    Task:
    Implement RandomHouse
    without 'if' statements

    View Slide

  257. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    Inheritance?

    View Slide

  258. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  259. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  260. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  261. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  262. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  263. Jan 2015
    @sandimetz

    View Slide

  264. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new

    View Slide

  265. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'

    View Slide

  266. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'

    View Slide

  267. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    puts  randomhouse.line(3)
    =>  'This  is  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  
    that  ate.'

    View Slide

  268. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    puts  randomhouse.line(3)
    =>  'This  is  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  
    that  ate.'
    puts  randomhouse.line(12)
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  
    sowing  his  corn  that  kept  the  dog  that  worried  the  priest  all  shaven  and  
    shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  horse  and  
    the  hound  and  the  horn  that  belonged  to  the  malt  that  lay  in  the  cow  with  
    the  crumpled  horn  that  tossed  the  house  that  Jack  built  the  cat  that  
    killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'

    View Slide

  269. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    puts  randomhouse.line(3)
    =>  'This  is  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  
    that  ate.'
    puts  randomhouse.line(12)
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  
    sowing  his  corn  that  kept  the  dog  that  worried  the  priest  all  shaven  and  
    shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  horse  and  
    the  hound  and  the  horn  that  belonged  to  the  malt  that  lay  in  the  cow  with  
    the  crumpled  horn  that  tossed  the  house  that  Jack  built  the  cat  that  
    killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'

    View Slide

  270. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    puts  randomhouse.line(3)
    =>  'This  is  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  
    that  ate.'
    puts  randomhouse.line(12)
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  
    sowing  his  corn  that  kept  the  dog  that  worried  the  priest  all  shaven  and  
    shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  horse  and  
    the  hound  and  the  horn  that  belonged  to  the  malt  that  lay  in  the  cow  with  
    the  crumpled  horn  that  tossed  the  house  that  Jack  built  the  cat  that  
    killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'

    View Slide

  271. Jan 2015
    @sandimetz
    randomhouse  =  RandomHouse.new
    puts  randomhouse.line(1)
    =>  'This  is  the  rat  that  ate.'
    puts  randomhouse.line(2)
    =>  'This  is  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    puts  randomhouse.line(3)
    =>  'This  is  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  
    that  ate.'
    puts  randomhouse.line(12)
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  
    sowing  his  corn  that  kept  the  dog  that  worried  the  priest  all  shaven  and  
    shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  horse  and  
    the  hound  and  the  horn  that  belonged  to  the  malt  that  lay  in  the  cow  with  
    the  crumpled  horn  that  tossed  the  house  that  Jack  built  the  cat  that  
    killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'

    View Slide

  272. Jan 2015
    @sandimetz

    View Slide

  273. Jan 2015
    @sandimetz
    New Feature Request:

    View Slide

  274. Jan 2015
    @sandimetz
    New Feature Request:
    EchoHouse

    View Slide

  275. Jan 2015
    @sandimetz

    View Slide

  276. Jan 2015
    @sandimetz
    This  is  the  house  that  Jack  built  the  house  that  Jack  built.

    View Slide

  277. Jan 2015
    @sandimetz
    This  is  the  house  that  Jack  built  the  house  that  Jack  built.

    View Slide

  278. Jan 2015
    @sandimetz
    This  is  the  house  that  Jack  built  the  house  that  Jack  built.
    This  is  the  malt  that  lay  in  the  malt  that  lay  in  
                   the  house  that  Jack  built  the  house  that  Jack  built.

    View Slide

  279. Jan 2015
    @sandimetz
    This  is  the  house  that  Jack  built  the  house  that  Jack  built.
    This  is  the  malt  that  lay  in  the  malt  that  lay  in  
                   the  house  that  Jack  built  the  house  that  Jack  built.

    View Slide

  280. Jan 2015
    @sandimetz
    This  is  the  house  that  Jack  built  the  house  that  Jack  built.
    This  is  the  malt  that  lay  in  the  malt  that  lay  in  
                   the  house  that  Jack  built  the  house  that  Jack  built.
    This  is  the  rat  that  ate  the  rat  that  ate  
                   the  malt  that  lay  in  the  malt  that  lay  in  
                   the  house  that  Jack  built  the  house  that  Jack  built.

    View Slide

  281. Jan 2015
    @sandimetz
    class  House  
       def  recite  
           (1..data.length).map  {|i|  line(i)}.join("\n")  
       end  
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  282. Jan 2015
    @sandimetz
    class  House  
       def  recite  
           (1..data.length).map  {|i|  line(i)}.join("\n")  
       end  
       def  line(number)  
           "This  is  #{phrase(number)}.\n"  
       end  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  283. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  284. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  285. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  286. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  parts(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  287. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           data.last(number).join("  ")  
       end  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  288. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           parts(number).join("  ")  
       end  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  289. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
           parts(number).join("  ")  
       end  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  290. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  291. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    have

    View Slide

  292. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    ['the  rat  that  ate',  
     'the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built',  
     'the  house  that  Jack  built']
    want

    View Slide

  293. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end

    View Slide

  294. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    Task:
    Implement EchoHouse
    without 'if' statements

    View Slide

  295. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    Inheritance?

    View Slide

  296. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  297. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  298. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  299. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  300. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  301. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']

    View Slide

  302. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']

    View Slide

  303. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    super.zip(super)

    View Slide

  304. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    [['the  rat  that  ate','the  rat  that  ate'],  
     ['the  malt  that  lay  in','the  malt  that  lay  in'],  
     ['the  house  that  Jack  built','the  house  that  Jack  built']]
    super.zip(super)

    View Slide

  305. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    super.zip(super).flatten
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    [['the  rat  that  ate','the  rat  that  ate'],  
     ['the  malt  that  lay  in','the  malt  that  lay  in'],  
     ['the  house  that  Jack  built','the  house  that  Jack  built']]
    super.zip(super)

    View Slide

  306. Jan 2015
    @sandimetz
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    super.zip(super).flatten
    ['the  rat  that  ate',  
     'the  malt  that  lay  in',  
     'the  house  that  Jack  built']
    [['the  rat  that  ate','the  rat  that  ate'],  
     ['the  malt  that  lay  in','the  malt  that  lay  in'],  
     ['the  house  that  Jack  built','the  house  that  Jack  built']]
    super.zip(super)
    ['the  rat  that  ate','the  rat  that  ate',  
     'the  malt  that  lay  in','the  malt  that  lay  in',  
     'the  house  that  Jack  built','the  house  that  Jack  built']

    View Slide

  307. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
           data.last(number)  
       end  
       def  data  
               [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
                   #  ...  
                   'the  malt  that  lay  in',  
                   'the  house  that  Jack  built']  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  308. Jan 2015
    @sandimetz

    View Slide

  309. Jan 2015
    @sandimetz
    puts  EchoHouse.new.line(1)
    'This  is  the  house  that  Jack  built  the  house  that  Jack  built.'

    View Slide

  310. Jan 2015
    @sandimetz
    puts  EchoHouse.new.line(1)
    'This  is  the  house  that  Jack  built  the  house  that  Jack  built.'
    puts  EchoHouse.new.line(2)
    'This  is  the  malt  that  lay  in  the  malt  that  lay  in  the  house  that  Jack  built  the  
    house  that  Jack  built.'

    View Slide

  311. Jan 2015
    @sandimetz
    puts  EchoHouse.new.line(1)
    'This  is  the  house  that  Jack  built  the  house  that  Jack  built.'
    puts  EchoHouse.new.line(2)
    'This  is  the  malt  that  lay  in  the  malt  that  lay  in  the  house  that  Jack  built  the  
    house  that  Jack  built.'
    puts  EchoHouse.new.line(3)
    'This  is  the  rat  that  ate  the  rat  that  ate  the  malt  that  lay  in  the  malt  that  lay  in  
    the  house  that  Jack  built  the  house  that  Jack  built.'

    View Slide

  312. Jan 2015
    @sandimetz
    puts  EchoHouse.new.line(1)
    'This  is  the  house  that  Jack  built  the  house  that  Jack  built.'
    puts  EchoHouse.new.line(2)
    'This  is  the  malt  that  lay  in  the  malt  that  lay  in  the  house  that  Jack  built  the  
    house  that  Jack  built.'
    puts  EchoHouse.new.line(3)
    'This  is  the  rat  that  ate  the  rat  that  ate  the  malt  that  lay  in  the  malt  that  lay  in  
    the  house  that  Jack  built  the  house  that  Jack  built.'
    puts  EchoHouse.new.line(12)
    'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  horse  and  the  
    hound  and  the  horn  that  belonged  to  the  farmer  sowing  his  corn  that  kept  the  farmer  
    sowing  his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  rooster  
    that  crowed  in  the  morn  that  woke  the  priest  all  shaven  and  shorn  that  married  the  
    priest  all  shaven  and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  
    the  man  all  tattered  and  torn  that  kissed  the  maiden  all  forlorn  that  milked  the  
    maiden  all  forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  cow  
    with  the  crumpled  horn  that  tossed  the  dog  that  worried  the  dog  that  worried  the  cat  
    that  killed  the  cat  that  killed  the  rat  that  ate  the  rat  that  ate  the  malt  that  lay  
    in  the  malt  that  lay  in  the  house  that  Jack  built  the  house  that  Jack  built.'

    View Slide

  313. Jan 2015
    @sandimetz
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  314. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  315. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  316. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  317. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  318. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end
    What could possibly go wrong?

    View Slide

  319. Jan 2015
    @sandimetz

    View Slide

  320. Jan 2015
    @sandimetz
    New Feature Request:

    View Slide

  321. Jan 2015
    @sandimetz
    New Feature Request:
    RandomEchoHouse

    View Slide

  322. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  House  
       def  recite  
       def  line(number)  
       def  phrase(number)  
       def  parts(number)  
       def  data  
    end

    View Slide

  323. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  324. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  325. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    Duplicate some of the code?

    View Slide

  326. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    data
    parts

    View Slide

  327. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end  
    class  RandomEchoHouse  <  RandomHouse  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    data
    parts

    View Slide

  328. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end  
    class  RandomEchoHouse  <  RandomHouse  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    data
    parts

    View Slide

  329. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end  
    class  RandomEchoHouse  <  RandomHouse  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    parts

    View Slide

  330. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end  
    class  RandomEchoHouse  <  RandomHouse  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    Duplicate parts

    View Slide

  331. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    Duplicate parts

    View Slide

  332. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end  
    class  
    RandomEchoHouse  
    <  
    EchoHouse  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    Duplicate parts

    View Slide

  333. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end  
    class  
    RandomEchoHouse  
    <  
    EchoHouse  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    Duplicate parts

    View Slide

  334. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end  
    class  
    RandomEchoHouse  
    <  
    EchoHouse  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data
    Duplicate parts Inherit

    View Slide

  335. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end  
    class  
    RandomEchoHouse  
    <  
    EchoHouse  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    RandomEchoHouse
    <  RandomHouse <  EchoHouse
    Inherit data Duplicate
    Duplicate parts Inherit

    View Slide

  336. Jan 2015
    @sandimetz
    class  RandomHouse  <  House   class  EchoHouse  <  House  

    View Slide

  337. Jan 2015
    @sandimetz
    class  RandomHouse  <  House   class  EchoHouse  <  House  
    Duplicate all of the code!

    View Slide

  338. Jan 2015
    @sandimetz
    class  RandomHouse  <  House   class  EchoHouse  <  House  
    class  RandomEchoHouse  <  House  

    View Slide

  339. Jan 2015
    @sandimetz
    class  RandomHouse  <  House   class  EchoHouse  <  House  
    class  RandomEchoHouse  <  House  

    View Slide

  340. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  RandomEchoHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  341. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  RandomEchoHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  342. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  RandomEchoHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  343. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  RandomEchoHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  344. Jan 2015
    @sandimetz
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    class  EchoHouse  <  House  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end
    class  RandomEchoHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
       def  parts(number)  
           super.zip(super).flatten  
       end  
    end

    View Slide

  345. Jan 2015
    @sandimetz
    House

    View Slide

  346. Jan 2015
    @sandimetz
    House
    Random
    House
    Echo
    House

    View Slide

  347. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House

    View Slide

  348. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House

    View Slide

  349. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House
    Random
    House

    View Slide

  350. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House
    Random
    House

    View Slide

  351. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House
    Random
    House

    View Slide

  352. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House
    Random
    House
    Echo
    House

    View Slide

  353. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House
    Random
    House
    Echo
    House

    View Slide

  354. Jan 2015
    @sandimetz
    Echo
    House
    Random
    House
    Random
    House
    Echo
    House

    View Slide

  355. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House

    View Slide

  356. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House

    View Slide

  357. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  358. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  359. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  360. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  361. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  362. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  363. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  364. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House
    RandomEcho
    House

    View Slide

  365. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House

    View Slide

  366. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House

    View Slide

  367. Jan 2015
    @sandimetz
    Random
    House
    Echo
    House

    View Slide

  368. Jan 2015
    @sandimetz

    View Slide

  369. Jan 2015
    @sandimetz
    Inheritance

    View Slide

  370. Jan 2015
    @sandimetz
    Inheritance
    is for specialization

    View Slide

  371. Jan 2015
    @sandimetz
    Inheritance
    is for specialization
    is not for sharing code

    View Slide

  372. Jan 2015
    @sandimetz
    RandomHouse is-a House?

    View Slide

  373. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  374. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    What does RandomHouse change?

    View Slide

  375. Jan 2015
    @sandimetz
    Reveal how things differ
    by making them more alike

    View Slide

  376. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  377. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    Make this

    View Slide

  378. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end
    Make this
    More like this

    View Slide

  379. Jan 2015
    @sandimetz
    class  House  
       def  data  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
       end  
    end

    View Slide

  380. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               'the  farmer  sowing  his  corn  that  kept',  
               'the  rooster  that  crowed  in  the  morn  that  woke',  
               'the  priest  all  shaven  and  shorn  that  married',  
               'the  man  all  tattered  and  torn  that  kissed',  
               'the  maiden  all  forlorn  that  milked',  
               'the  cow  with  the  crumpled  horn  that  tossed',  
               'the  dog  that  worried',  
               'the  cat  that  killed',  
               'the  rat  that  ate',  
               'the  malt  that  lay  in',  
               'the  house  that  Jack  built']  
    end

    View Slide

  381. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
    end

    View Slide

  382. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           DATA  
       end  
    end

    View Slide

  383. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           DATA  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  384. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           @data  ||=  DATA  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  385. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           @data  ||=  DATA  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  DATA.shuffle  
       end  
    end

    View Slide

  386. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           @data  ||=  DATA  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  DATA.shuffle  
       end  
    end
    What changed?

    View Slide

  387. Jan 2015
    @sandimetz
    Name the concept

    View Slide

  388. Jan 2015
    @sandimetz
    House
    RandomHouse

    View Slide

  389. Jan 2015
    @sandimetz
    House DATA
    RandomHouse DATA

    View Slide

  390. Jan 2015
    @sandimetz
    House DATA
    RandomHouse DATA shuffle

    View Slide

  391. Jan 2015
    @sandimetz
    class
    House DATA
    RandomHouse DATA shuffle

    View Slide

  392. Jan 2015
    @sandimetz
    class data
    House DATA
    RandomHouse DATA shuffle

    View Slide

  393. Jan 2015
    @sandimetz
    class data ?????
    House DATA
    RandomHouse DATA shuffle

    View Slide

  394. Jan 2015
    @sandimetz
    class data random??
    House DATA
    RandomHouse DATA shuffle

    View Slide

  395. Jan 2015
    @sandimetz
    class data order!
    House DATA
    RandomHouse DATA shuffle

    View Slide

  396. Jan 2015
    @sandimetz
    class data order
    House DATA
    RandomHouse DATA shuffle

    View Slide

  397. Jan 2015
    @sandimetz
    class data order
    House DATA
    RandomHouse DATA shuffle
    This is not nothing

    View Slide

  398. Jan 2015
    @sandimetz
    class data order
    House DATA
    RandomHouse DATA shuffle
    It's an order algorithm

    View Slide

  399. Jan 2015
    @sandimetz
    class data order
    House DATA
    RandomHouse DATA shuffle
    It's an order algorithm
    just as valid as this one

    View Slide

  400. Jan 2015
    @sandimetz
    Order is-a House?

    View Slide

  401. Jan 2015
    @sandimetz
    Orderer is a role

    View Slide

  402. Jan 2015
    @sandimetz
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  403. Jan 2015
    @sandimetz
    class  DefaultOrder  
    end  
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  404. Jan 2015
    @sandimetz
    class  DefaultOrder  
       def  order(data)  
       end  
    end  
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  405. Jan 2015
    @sandimetz
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end  
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  406. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           DATA  
       end  
    end  
    class  RandomHouse  <  House  
       def  data  
           @data  ||=  super.shuffle  
       end  
    end

    View Slide

  407. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           DATA  
       end  
    end

    View Slide

  408. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       def  data  
           DATA  
       end  
         #  ...  
    end

    View Slide

  409. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       attr_reader  :data  
       def  data  
           DATA  
       end  
         #  ...  
    end

    View Slide

  410. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
       def  data  
           DATA  
       end  
         #  ...  
    end

    View Slide

  411. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end

    View Slide

  412. Jan 2015
    @sandimetz
    class  House  
       DATA  =  
           [  'the  horse  and  the  hound  and  the  horn  that  belonged  to',  
               #  ...  
             'the  house  that  Jack  built']  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end

    View Slide

  413. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end

    View Slide

  414. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end

    View Slide

  415. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end
    Remove 'ordering' responsibility from House

    View Slide

  416. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize  
           @data  =  DATA  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end

    View Slide

  417. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  DATA  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end

    View Slide

  418. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =                              DATA  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end

    View Slide

  419. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end

    View Slide

  420. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)

    View Slide

  421. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'

    View Slide

  422. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)  
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'

    View Slide

  423. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)  
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    More code

    View Slide

  424. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)  
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    More code
    Same behavior

    View Slide

  425. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)  
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    More code
    Same behavior
    Awesome

    View Slide

  426. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)  
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  
    his  corn  that  kept  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  
    and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  maiden  all  
    forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  that  worried  
    the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'

    View Slide

  427. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new.line(12)
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  428. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(                                                ).line(12)
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  429. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  430. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  sowing  his  corn  
    that  kept  the  dog  that  worried  the  priest  all  shaven  and  shorn  that  married  the  man  
    all  tattered  and  torn  that  kissed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  malt  that  lay  in  the  cow  with  the  crumpled  horn  that  tossed  the  house  that  Jack  
    built  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  431. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  sowing  his  corn  
    that  kept  the  dog  that  worried  the  priest  all  shaven  and  shorn  that  married  the  man  
    all  tattered  and  torn  that  kissed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  malt  that  lay  in  the  cow  with  the  crumpled  horn  that  tossed  the  house  that  Jack  
    built  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  432. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  sowing  his  corn  
    that  kept  the  dog  that  worried  the  priest  all  shaven  and  shorn  that  married  the  man  
    all  tattered  and  torn  that  kissed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  malt  that  lay  in  the  cow  with  the  crumpled  horn  that  tossed  the  house  that  Jack  
    built  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  433. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  farmer  sowing  his  corn  
    that  kept  the  dog  that  worried  the  priest  all  shaven  and  shorn  that  married  the  man  
    all  tattered  and  torn  that  kissed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  malt  that  lay  in  the  cow  with  the  crumpled  horn  that  tossed  the  house  that  Jack  
    built  the  cat  that  killed  the  maiden  all  forlorn  that  milked  the  rat  that  ate.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end

    View Slide

  434. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  cat  that  killed  the  cow  
    with  the  crumpled  horn  that  tossed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  farmer  sowing  his  corn  that  kept  the  priest  all  shaven  and  shorn  that  married  
    the  man  all  tattered  and  torn  that  kissed  the  house  that  Jack  built  the  malt  that  lay  
    in  the  rat  that  ate  the  maiden  all  forlorn  that  milked  the  dog  that  worried.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end
    Composition

    View Slide

  435. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    puts  House.new(orderer:  RandomOrder.new).line(12)  
    =>  'This  is  the  rooster  that  crowed  in  the  morn  that  woke  the  cat  that  killed  the  cow  
    with  the  crumpled  horn  that  tossed  the  horse  and  the  hound  and  the  horn  that  belonged  
    to  the  farmer  sowing  his  corn  that  kept  the  priest  all  shaven  and  shorn  that  married  
    the  man  all  tattered  and  torn  that  kissed  the  house  that  Jack  built  the  malt  that  lay  
    in  the  rat  that  ate  the  maiden  all  forlorn  that  milked  the  dog  that  worried.'
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end
    Inject an object
    to play the role
    of the thing that varies

    View Slide

  436. Jan 2015
    @sandimetz
    Echo?

    View Slide

  437. Jan 2015
    @sandimetz
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end

    View Slide

  438. Jan 2015
    @sandimetz
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end  
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end

    View Slide

  439. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end

    View Slide

  440. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  initialize(orderer:  DefaultOrder.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  441. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  442. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  443. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data  =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  444. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  445. Jan 2015
    @sandimetz
    class  House  
       attr_reader                          :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  446. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  447. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  448. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
       def  parts(number)  
         data.last(number)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  449. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
       def  parts(number)  
                                             data.last(number)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  450. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
       def  parts(number)  
           formatter.format(data.last(number))  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  451. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  452. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  453. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    puts  House.new.line(12)
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  454. Jan 2015
    @sandimetz
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    puts  House.new.line(12)
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  farmer  sowing  his  corn  that  kept  the  
    rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  and  shorn  that  married  the  man  all  tattered  
    and  torn  that  kissed  the  maiden  all  forlorn  that  milked  the  cow  with  the  crumpled  horn  that  tossed  the  dog  
    that  worried  the  cat  that  killed  the  rat  that  ate  the  malt  that  lay  in  the  house  that  Jack  built.'
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end

    View Slide

  455. Jan 2015
    @sandimetz
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end

    View Slide

  456. Jan 2015
    @sandimetz
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    puts  House.new(formatter:  EchoFormatter.new).line(12)
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end

    View Slide

  457. Jan 2015
    @sandimetz
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end
    class  House  
       attr_reader  :formatter,  :data  
       def  
    initialize(orderer:  
    DefaultOrder.new,  
    formatter:  
    DefaultFormatter.new)  
           @formatter  =  formatter  
           @data            =  orderer.order(DATA)  
       end  
         #  ...  
    end
    puts  House.new(formatter:  EchoFormatter.new).line(12)
    =>  'This  is  the  horse  and  the  hound  and  the  horn  that  belonged  to  the  horse  and  the  hound  and  the  horn  that  
    belonged  to  the  farmer  sowing  his  corn  that  kept  the  farmer  sowing  his  corn  that  kept  the  rooster  that  
    crowed  in  the  morn  that  woke  the  rooster  that  crowed  in  the  morn  that  woke  the  priest  all  shaven  and  shorn  
    that  married  the  priest  all  shaven  and  shorn  that  married  the  man  all  tattered  and  torn  that  kissed  the  man
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end

    View Slide

  458. Jan 2015
    @sandimetz
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end
    Orderer Role

    View Slide

  459. Jan 2015
    @sandimetz
    class  DefaultFormatter  
       def  format(parts)  
           parts  
       end  
    end
    class  EchoFormatter  
       def  format(parts)  
           parts.zip(parts).flatten  
       end  
    end
    class  DefaultOrder  
       def  order(data)  
           data  
       end  
    end
    class  RandomOrder  
       def  order(data)  
           data.shuffle  
       end  
    end
    Orderer Role Formatter Role

    View Slide

  460. Jan 2015
    @sandimetz
    puts  House.new.line(12)

    View Slide

  461. Jan 2015
    @sandimetz

    View Slide

  462. Jan 2015
    @sandimetz
    puts  House.new.recite

    View Slide

  463. Jan 2015
    @sandimetz
    puts  House.new.recite
    puts  House.new(orderer:  RandomOrder.new).recite

    View Slide

  464. Jan 2015
    @sandimetz
    puts  House.new.recite
    puts  House.new(orderer:  RandomOrder.new).recite
    puts  House.new(formatter:  EchoFormatter.new).recite

    View Slide

  465. Jan 2015
    @sandimetz
    puts  House.new.recite
    puts  House.new(orderer:  RandomOrder.new).recite
    puts  House.new(formatter:  EchoFormatter.new).recite
    puts  House.new(orderer:      RandomOrder.new,  
                                 formatter:  EchoFormatter.new).recite

    View Slide

  466. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    More code?

    View Slide

  467. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite

    View Slide

  468. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Less code!

    View Slide

  469. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Less code!
    No duplication

    View Slide

  470. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Less code!
    Pluggable behavior

    View Slide

  471. Jan 2015
    @sandimetz
    House
    Echo
    House
    Random
    House

    View Slide

  472. Jan 2015
    @sandimetz
    House

    View Slide

  473. Jan 2015
    @sandimetz
    House

    View Slide

  474. Jan 2015
    @sandimetz
    House
    1) Isolate the thing that varies

    View Slide

  475. Jan 2015
    @sandimetz
    House
    1) Isolate the thing that varies

    View Slide

  476. Jan 2015
    @sandimetz
    House
    1) Isolate the thing that varies

    View Slide

  477. Jan 2015
    @sandimetz
    House

    View Slide

  478. Jan 2015
    @sandimetz
    House

    View Slide

  479. Jan 2015
    @sandimetz
    House
    2) Name the Concept

    View Slide

  480. Jan 2015
    @sandimetz
    House
    2) Name the Concept

    View Slide

  481. Jan 2015
    @sandimetz
    House
    Order Format

    View Slide

  482. Jan 2015
    @sandimetz
    House
    Order Format
    3) Define the Role

    View Slide

  483. Jan 2015
    @sandimetz
    House
    Order Format
    3) Define the Role

    View Slide

  484. Jan 2015
    @sandimetz
    House
    Orderer Formatter

    View Slide

  485. Jan 2015
    @sandimetz
    House
    Orderer Formatter
    4) Inject the player

    View Slide

  486. Jan 2015
    @sandimetz
    House
    Orderer Formatter

    View Slide

  487. Jan 2015
    @sandimetz
    House
    Orderer Formatter

    View Slide

  488. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite

    View Slide

  489. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Composition

    View Slide

  490. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Composition
    +
    Dependency Injection

    View Slide

  491. Jan 2015
    @sandimetz
    puts  House.new.recite  
    puts  House.new(orderer:  RandomOrder.new).recite  
    puts  House.new(formatter:  EchoFormatter.new).recite  
    puts  House.new(orderer:      RandomOrder.new,    
                                 formatter:  EchoFormatter.new).recite
    Object-Oriented Design

    View Slide

  492. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse
    Message Centric
    Abstraction Seeking

    View Slide

  493. Jan 2015
    @sandimetz
    Smalltalk Infected
    Condition Averse
    Message Centric
    Abstraction Seeking

    View Slide

  494. Jan 2015
    @sandimetz
    Summary

    View Slide

  495. Jan 2015
    @sandimetz

    View Slide

  496. Jan 2015
    @sandimetz
    If you're talking to nil

    View Slide

  497. Jan 2015
    @sandimetz
    If you're talking to nil
    it's something

    View Slide

  498. Jan 2015
    @sandimetz
    Null Object Pattern
    Active Nothing

    View Slide

  499. Jan 2015
    @sandimetz

    View Slide

  500. Jan 2015
    @sandimetz
    Ware Inheritance

    View Slide

  501. Jan 2015
    @sandimetz
    Ware Inheritance
    It is not for sharing behavior

    View Slide

  502. Jan 2015
    @sandimetz
    There's no such thing as
    one specialization

    View Slide

  503. Jan 2015
    @sandimetz

    View Slide

  504. Jan 2015
    @sandimetz
    Isolate the thing that varies

    View Slide

  505. Jan 2015
    @sandimetz
    Isolate the thing that varies
    Name the concept

    View Slide

  506. Jan 2015
    @sandimetz
    Isolate the thing that varies
    Name the concept
    Define the role

    View Slide

  507. Jan 2015
    @sandimetz
    Isolate the thing that varies
    Name the concept
    Define the role
    Inject the players

    View Slide

  508. Jan 2015
    @sandimetz
    Believe in nothing

    View Slide

  509. Jan 2015
    @sandimetz
    Nothing
    is always
    Something

    View Slide

  510. Jan 2015
    @sandimetz
    Sandi Metz
    @sandimetz
    http://sandimetz.com

    View Slide

  511. Jan 2015
    @sandimetz
    http://poodr.com

    View Slide

  512. Jan 2015
    @sandimetz
    http://99bottlesbook.com
    Practical Programming Book
    99 Bottles of OOP

    View Slide

  513. Jan 2015
    @sandimetz
    Next Public Course
    POODNYC
    Oct 19-21, 2015
    New York City

    View Slide

  514. Jan 2015
    @sandimetz
    Stickers?

    View Slide

  515. Jan 2015
    @sandimetz
    Stickers?

    View Slide

  516. Jan 2015
    @sandimetz
    Temporary
    Tattoos!

    View Slide

  517. Jan 2015
    @sandimetz
    Thanks

    View Slide

  518. Jan 2015
    @sandimetz
    Sandi Metz
    @sandimetz
    http://sandimetz.com

    View Slide