SlideShare a Scribd company logo
The revenge of method_missing()




       Paolo “Nusco” Perrotta
Should I use method_missing()
  to remove duplication from
my code, or should I avoid it
       like the plague?

      Paolo “Nusco” Perrotta
disclaimer
Person.find_by_user_name_and_password name, pwd
class NilClass
  # ...

  def method_missing(method, *args, &block)
    if klass = METHOD_CLASS_MAP[method]
      raise_nil_warning_for klass, method, caller
    else
      super
    end
  end
end
end of disclaimer
class InfoDesk
  def flights
    # ...
  end

  def trains
    # ...
  end

  def hotels
    # ...
  end

  # ...
end
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def flights
    return “Out for lunch” if Clock.lunch_time?
    @desk.flights
  end

  def trains
    return “Out for lunch” if Clock.lunch_time?
    @desk.local_transports
  end

  def hotels
    return “Out for lunch” if Clock.lunch_time?
    @desk.local_transports
  end

  # ...
end
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def method_missing(name, *args)
    return “Out for lunch” if Clock.lunch_time?
    @desk.send(name, *args)
  end
end

# At 12:30...
Sign.new.flights    # => “Out for lunch”
Ghost Methods
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  InfoDesk.public_instance_methods.each do |m|
    define_method(m) do
      return “Out for lunch” if Clock.lunch_time?
      @desk.send(m)
    end
  end
end
Ghost Methods
      vs.
Dynamic Methods
the four pitfalls
of method_missing()
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def method_missing(name, *args)
    return “Out for lunch” if Clock.lunch_time?
    @desk.send(name, *args)
  end
end
we have a problem
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def is_it_lunch_time_yet?
    Clock.lunch_time?
  end

  def method_missing(name, *args)
    return “Out for lunch” if is_it_lunchtime_yet?
    @desk.send(name, *args)
  end
end

# At 12:30...
Sign.new.flights   # => ?
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def is_it_lunch_time_yet?
    Clock.lunch_time?
  end

  def method_missing(name, *args)
    return “Out for lunch” if is_it_lunchtime_yet?
    @desk.send(name, *args)
  end
end

# At 12:30...
Sign.new.flights   # => ?
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def is_it_lunch_time_yet?
    Clock.lunch_time?
  end

  def method_missing(name, *args)
    return “Out for lunch” if is_it_lunchtime_yet?
    @desk.send(name, *args)
  end
end

# At 12:30...
Sign.new.flights   # => SystemStackError: stack level too deep
the first pitfall:




 the Ghost House
class Sign
  def initialize
    @desk = InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    return “Out for lunch” if Clock.lunch_time?
    @desk.send(name, *args)
  end
end
we have a problem
Sign.new.respond_to? :flights   # => false
the second pitfall:




  the Liar Object
class Sign
  def initialize
    @desk = ::InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    return “Out for lunch” if Clock.lunch_time?
    @desk.send(name, *args)
  end

  def respond_to?(method)
    @desk.respond_to?(method) || super
  end
end

Sign.new.respond_to? :flights   # => true
we have a problem
class InfoDesk
  def flights
    # ...
  end

  def local_transports
    # ...
  end

  # ...

  def display
    # ...
  end
end
Sign.new.display   # => #<Sign:0x000001008451b0>
the third pitfall:




  the Fake Ghost
class Sign
  instance_methods.each do |m|
    undef_method m unless m.to_s =~ /^__|object_id/
  end

  def initialize
    @desk = InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    return "Out for lunch" if Clock.lunch_time?
    @desk.send(name, *args)
  end

  def respond_to?(method)
    @desk.respond_to? method || super
  end
end

Sign.new.display   # => InfoDesk#display() called
class Sign < BasicObject
  def initialize
    @desk = ::InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    return “Out for lunch” if ::Clock.lunch_time?
    @desk.send(name, *args)
  end

  def respond_to?(method)
    @desk.respond_to? method || super
  end
end

Sign.new.display   # => InfoDesk#display() called
we have a problem
    (this is getting old already)
the fourth pitfall:




  the Snail Ghost
class Sign < BasicObject
  def initialize
    @desk = ::InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    singleton_class.send :define_method, name do
      return “Out for lunch” if ::Clock.lunch_time?
      @desk.send name
    end
    send name
  end

  def respond_to?(method)
    @desk.respond_to? method || super
  end
end

# At 12:30...
Sign.new.flights # => ?
class Sign < BasicObject
  def initialize
    @desk = ::InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    singleton_class.send :define_method, name do
      return “Out for lunch” if ::Clock.lunch_time?
      @desk.send name
    end
    send name
  end

  def respond_to?(method)
    @desk.respond_to? method || super
  end
end

# At 12:30...
Sign.new.flights # => SystemStackError: stack level too deep
class Sign < BasicObject
  def initialize
    @desk = ::InfoDesk.new
  end

  def method_missing(name, *args)
    return super unless @desk.respond_to? name

    singleton_class.send :define_method, name do
      return “Out for lunch” if ::Clock.lunch_time?
      @desk.send name
    end
    send name
  end

  def respond_to?(method)
    @desk.respond_to? method || super
  end
end

# At 12:30...
Sign.new.flights # => SystemStackError: stack level too deep
should I use method_missing()
   to remove duplication in
           my code?
not if you can use
define_method() instead
just a rule of thumb
remember the four pitfalls:
         the Ghost House

         the Liar Object

         the Fake Ghost

         the Snail Ghost
thank you.
The Revenge of method_missing()

More Related Content

What's hot

Coding Guidelines - Crafting Clean Code
Coding Guidelines - Crafting Clean CodeCoding Guidelines - Crafting Clean Code
Coding Guidelines - Crafting Clean Code
Ganesh Samarthyam
 
Ruby on rails presentation
Ruby on rails presentationRuby on rails presentation
Ruby on rails presentation
Synbioz
 
Python Programming Essentials - M16 - Control Flow Statements and Loops
Python Programming Essentials - M16 - Control Flow Statements and LoopsPython Programming Essentials - M16 - Control Flow Statements and Loops
Python Programming Essentials - M16 - Control Flow Statements and Loops
P3 InfoTech Solutions Pvt. Ltd.
 
Rust Intro
Rust IntroRust Intro
Rust Intro
Arthur Gavkaluk
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
Kevlin Henney
 
Refactoring
RefactoringRefactoring
Refactoringnkaluva
 
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Codemotion
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Codemotion
 
Fog City Ruby - Triple Equals Black Magic with speaker notes
Fog City Ruby - Triple Equals Black Magic with speaker notesFog City Ruby - Triple Equals Black Magic with speaker notes
Fog City Ruby - Triple Equals Black Magic with speaker notes
Brandon Weaver
 
Python data structures
Python data structuresPython data structures
Python data structures
Harry Potter
 
Unit vii wp ppt
Unit vii wp pptUnit vii wp ppt
Unit vii wp ppt
Bhavsingh Maloth
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
Benjamin Bock
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Python basics
Python basicsPython basics
Python Modules, Packages and Libraries
Python Modules, Packages and LibrariesPython Modules, Packages and Libraries
Python Modules, Packages and Libraries
Venugopalavarma Raja
 

What's hot (16)

Coding Guidelines - Crafting Clean Code
Coding Guidelines - Crafting Clean CodeCoding Guidelines - Crafting Clean Code
Coding Guidelines - Crafting Clean Code
 
Ruby on rails presentation
Ruby on rails presentationRuby on rails presentation
Ruby on rails presentation
 
Python Programming Essentials - M16 - Control Flow Statements and Loops
Python Programming Essentials - M16 - Control Flow Statements and LoopsPython Programming Essentials - M16 - Control Flow Statements and Loops
Python Programming Essentials - M16 - Control Flow Statements and Loops
 
Rust Intro
Rust IntroRust Intro
Rust Intro
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
 
Refactoring
RefactoringRefactoring
Refactoring
 
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
Lucio Floretta - TensorFlow and Deep Learning without a PhD - Codemotion Mila...
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
Fog City Ruby - Triple Equals Black Magic with speaker notes
Fog City Ruby - Triple Equals Black Magic with speaker notesFog City Ruby - Triple Equals Black Magic with speaker notes
Fog City Ruby - Triple Equals Black Magic with speaker notes
 
Python data structures
Python data structuresPython data structures
Python data structures
 
Unit vii wp ppt
Unit vii wp pptUnit vii wp ppt
Unit vii wp ppt
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
R Debugging
R DebuggingR Debugging
R Debugging
 
Python basics
Python basicsPython basics
Python basics
 
Python Modules, Packages and Libraries
Python Modules, Packages and LibrariesPython Modules, Packages and Libraries
Python Modules, Packages and Libraries
 

Similar to The Revenge of method_missing()

Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101Nando Vieira
 
A limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyA limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced Ruby
Vysakh Sreenivasan
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
Christian KAKESA
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosEdgar Suarez
 
Professional-grade software design
Professional-grade software designProfessional-grade software design
Professional-grade software design
Brian Fenton
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
Jano Suchal
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
Monads in Ruby - Victor Zagorodny
Monads in Ruby - Victor ZagorodnyMonads in Ruby - Victor Zagorodny
Monads in Ruby - Victor Zagorodny
Ruby Meditation
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
Arturo Herrero
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
niklal
 
Tres Gemas De Ruby
Tres Gemas De RubyTres Gemas De Ruby
Tres Gemas De Ruby
Leonardo Soto
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
Intro to ruby
Intro to rubyIntro to ruby
Intro to ruby
Heather Campbell
 
Java VS Python
Java VS PythonJava VS Python
Java VS Python
Simone Federici
 
Dsl
DslDsl
Dsl
phoet
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
Garth Gilmour
 
PHP Technical Questions
PHP Technical QuestionsPHP Technical Questions
PHP Technical Questions
Pankaj Jha
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Lorenzo Dematté
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
Baruch Sadogursky
 
Ruby basic3
Ruby basic3Ruby basic3
Ruby basic3
Ho Yin Liu
 

Similar to The Revenge of method_missing() (20)

Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101
 
A limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyA limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced Ruby
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 
Professional-grade software design
Professional-grade software designProfessional-grade software design
Professional-grade software design
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Monads in Ruby - Victor Zagorodny
Monads in Ruby - Victor ZagorodnyMonads in Ruby - Victor Zagorodny
Monads in Ruby - Victor Zagorodny
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 
Tres Gemas De Ruby
Tres Gemas De RubyTres Gemas De Ruby
Tres Gemas De Ruby
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Intro to ruby
Intro to rubyIntro to ruby
Intro to ruby
 
Java VS Python
Java VS PythonJava VS Python
Java VS Python
 
Dsl
DslDsl
Dsl
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
 
PHP Technical Questions
PHP Technical QuestionsPHP Technical Questions
PHP Technical Questions
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
Ruby basic3
Ruby basic3Ruby basic3
Ruby basic3
 

Recently uploaded

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 

Recently uploaded (20)

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 

The Revenge of method_missing()

  • 1. The revenge of method_missing() Paolo “Nusco” Perrotta
  • 2. Should I use method_missing() to remove duplication from my code, or should I avoid it like the plague? Paolo “Nusco” Perrotta
  • 3.
  • 6. class NilClass # ... def method_missing(method, *args, &block) if klass = METHOD_CLASS_MAP[method] raise_nil_warning_for klass, method, caller else super end end end
  • 8. class InfoDesk def flights # ... end def trains # ... end def hotels # ... end # ... end
  • 9. class Sign def initialize @desk = InfoDesk.new end def flights return “Out for lunch” if Clock.lunch_time? @desk.flights end def trains return “Out for lunch” if Clock.lunch_time? @desk.local_transports end def hotels return “Out for lunch” if Clock.lunch_time? @desk.local_transports end # ... end
  • 10.
  • 11.
  • 12. class Sign def initialize @desk = InfoDesk.new end def method_missing(name, *args) return “Out for lunch” if Clock.lunch_time? @desk.send(name, *args) end end # At 12:30... Sign.new.flights # => “Out for lunch”
  • 14. class Sign def initialize @desk = InfoDesk.new end InfoDesk.public_instance_methods.each do |m| define_method(m) do return “Out for lunch” if Clock.lunch_time? @desk.send(m) end end end
  • 15. Ghost Methods vs. Dynamic Methods
  • 16. the four pitfalls of method_missing()
  • 17. class Sign def initialize @desk = InfoDesk.new end def method_missing(name, *args) return “Out for lunch” if Clock.lunch_time? @desk.send(name, *args) end end
  • 18. we have a problem
  • 19. class Sign def initialize @desk = InfoDesk.new end def is_it_lunch_time_yet? Clock.lunch_time? end def method_missing(name, *args) return “Out for lunch” if is_it_lunchtime_yet? @desk.send(name, *args) end end # At 12:30... Sign.new.flights # => ?
  • 20. class Sign def initialize @desk = InfoDesk.new end def is_it_lunch_time_yet? Clock.lunch_time? end def method_missing(name, *args) return “Out for lunch” if is_it_lunchtime_yet? @desk.send(name, *args) end end # At 12:30... Sign.new.flights # => ?
  • 21. class Sign def initialize @desk = InfoDesk.new end def is_it_lunch_time_yet? Clock.lunch_time? end def method_missing(name, *args) return “Out for lunch” if is_it_lunchtime_yet? @desk.send(name, *args) end end # At 12:30... Sign.new.flights # => SystemStackError: stack level too deep
  • 22. the first pitfall: the Ghost House
  • 23. class Sign def initialize @desk = InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name return “Out for lunch” if Clock.lunch_time? @desk.send(name, *args) end end
  • 24. we have a problem
  • 26. the second pitfall: the Liar Object
  • 27. class Sign def initialize @desk = ::InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name return “Out for lunch” if Clock.lunch_time? @desk.send(name, *args) end def respond_to?(method) @desk.respond_to?(method) || super end end Sign.new.respond_to? :flights # => true
  • 28. we have a problem
  • 29. class InfoDesk def flights # ... end def local_transports # ... end # ... def display # ... end end
  • 30. Sign.new.display # => #<Sign:0x000001008451b0>
  • 31.
  • 32.
  • 33. the third pitfall: the Fake Ghost
  • 34. class Sign instance_methods.each do |m| undef_method m unless m.to_s =~ /^__|object_id/ end def initialize @desk = InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name return "Out for lunch" if Clock.lunch_time? @desk.send(name, *args) end def respond_to?(method) @desk.respond_to? method || super end end Sign.new.display # => InfoDesk#display() called
  • 35. class Sign < BasicObject def initialize @desk = ::InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name return “Out for lunch” if ::Clock.lunch_time? @desk.send(name, *args) end def respond_to?(method) @desk.respond_to? method || super end end Sign.new.display # => InfoDesk#display() called
  • 36. we have a problem (this is getting old already)
  • 37.
  • 38. the fourth pitfall: the Snail Ghost
  • 39. class Sign < BasicObject def initialize @desk = ::InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name singleton_class.send :define_method, name do return “Out for lunch” if ::Clock.lunch_time? @desk.send name end send name end def respond_to?(method) @desk.respond_to? method || super end end # At 12:30... Sign.new.flights # => ?
  • 40. class Sign < BasicObject def initialize @desk = ::InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name singleton_class.send :define_method, name do return “Out for lunch” if ::Clock.lunch_time? @desk.send name end send name end def respond_to?(method) @desk.respond_to? method || super end end # At 12:30... Sign.new.flights # => SystemStackError: stack level too deep
  • 41. class Sign < BasicObject def initialize @desk = ::InfoDesk.new end def method_missing(name, *args) return super unless @desk.respond_to? name singleton_class.send :define_method, name do return “Out for lunch” if ::Clock.lunch_time? @desk.send name end send name end def respond_to?(method) @desk.respond_to? method || super end end # At 12:30... Sign.new.flights # => SystemStackError: stack level too deep
  • 42.
  • 43.
  • 44. should I use method_missing() to remove duplication in my code?
  • 45. not if you can use define_method() instead
  • 46. just a rule of thumb
  • 47. remember the four pitfalls: the Ghost House the Liar Object the Fake Ghost the Snail Ghost

Editor's Notes

  1. aka...\n
  2. I&amp;#x2019;m assuming you know what m_m() is, but I&amp;#x2019;m also going to show a basic example\n
  3. - question at RubyKaigi\n- blog post on RubyLearning\n- disclaimer: this is about using method_missing() even when there are alternate techniques\n- there are cases where there is no alternative\n
  4. \n
  5. \n
  6. (accessors, writing a DSL - think hard before you do this!)\nnot just for cutesy\n
  7. example: whiny nils\n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. ghost methods\n
  15. \n
  16. ghost methods\n
  17. my own experiment\n
  18. back to our original solution\nlet&amp;#x2019;s do some refactoring\n
  19. \n
  20. \n
  21. \n
  22. \n
  23. - any method you can call is a ghost\n - fix: always select the methods you&apos;re using\n\n\n
  24. - fix: always remember to call super\n\n
  25. \n
  26. \n
  27. no respond_to?\n(also, breaks the IDE and searches)\n\n
  28. - fix: always implement respond_to?)\n- limitations of fix (methods(), etc)\n\n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. - fix: inherit from a Blank Slate\n\n
  35. the &amp;#x201C;scary&amp;#x201D; solution\nwhich methods should I remove exactly?\n
  36. \n
  37. \n
  38. \n
  39. \n
  40. - fix: (Reincarnation) lazily define methods with define_method() in method_missing()\n\n\n
  41. ...but it doesn&amp;#x2019;t work!\n
  42. why it breaks\nwhat a mess! the experiment is over...\n
  43. talking to jake scruggs\n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n