SlideShare a Scribd company logo
1 of 46
Download to read offline
refinements
the worst feature you ever loved
paolo @nusco perrotta
obvious
“Obvious” problems are those that you can solve yourself, if you have some time and knowledge.
non-obvious
“Non-obvious” problems require more effort. You might not know how to solve them at first.
deep
“Deep” problems might not even have an optimal solution. You have to experiment.
-1-
why refinements
Let’s look at the problem that refinements are designed to solve.
class String
def shout
upcase + "!"
end
end
"hello".shout # => "HELLO!"
monkeypatching
In Ruby, you can do this.
three use cases
Three of the most important use cases for monkeypatching.
describe Fixnum do
it "can be added" do
(2 + 2).should == 4
end
end
domain specific languages
require "active_support/all"
1.hour + 20.minutes # => 4800 seconds
convenience methods
method wrappers
class String
alias_method :old_length, :length
def length
old_length > 5 ? "long" : "short"
end
end
"War and Peace".length # => "long"
class String
alias_method :old_length, :length
def length
old_length > 5 ? "long" : "short"
end
end
"War and Peace".length # => "long"
!This example also shows why monkeypatches are dangerous: because they are global.
local monkeypatches
This is what we want, and what Refinements are.
-2-
refinements
Let’s look at Refinements, the way they were originally conceived.
module StringExtensions
refine String do
def shout
upcase + "!"
end
end
end
defining a refinement
module ModuleThatUsesTheRefinement
using StringExtensions
"hello".shout # => "HELLO!"
end
using a refinement
Refinement in a class/module. Only active in the marked area.
using StringExtensions
"hello".shout # => "HELLO!"
# EOF
using a refinement
Refinement at the top level. Only active in the marked area.
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
class C
"hello".shout # => ?
end
…but will it work here?
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
class D < C
"hello".shout # => ?
end
…or here?
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
C.class_eval do
"hello".shout # => ?
end
…or here?
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
C.class_eval do
"hello".shout # => "HELLO!"
end
dynamic scope
The original proposal (Dynamically Scoped Refinements) says yes, in all three cases.
-3-
refinement gotchas
But people found potential problems with this.
confusing code
def add(x, y)
x + y
end
SomeClass.class_eval do
add(1, 1) # => 2
end
SomeOtherClass.class_eval do
add(1, 1) # => "11"
end
using FloatPointMath # refines Fixnum#+
add(1, 1) # => 2.0
You need to look at the implementations to understand the interface.
slows down the language
def add(x, y)
x + y
end
SomeClass.class_eval do
add(1, 1) # => 2
end
SomeOtherClass.class_eval do
add(1, 1) # => "11"
end
using FloatPointMath # refines Fixnum#+
add(1, 1) # => 2.0
The interpreter also needs to do the same, so Refinements can slow down the entire interpreter.
security threat
def add(x, y)
x + y
end
SomeClass.class_eval do
add(1, 1) # => 2
end
SomeOtherClass.class_eval do
add(1, 1) # => "11"
end
using FloatPointMath # refines Fixnum#+
add(1, 1) # => 2.0
Less understanding potentially means less security.
surprising corner cases
def add(x, y)
x + y
end
SomeClass.class_eval do
add(1, 1) # => 2
end
SomeOtherClass.class_eval do
add(1, 1) # => "11"
end
using FloatPointMath # refines Fixnum#+
add(1, 1) # => 2.0
Some things might not work as you expect. (For example, the last line doesn’t work in irb).
•they fix monkeypatches
refinements: the good
The good of Dynamically Scoped Refinements.
•they make Ruby code potentially confusing
•they impact performance
•they impact security
•they have weird corner cases
refinements: the bad_
The bad of Dynamically Scoped Refinements.
are dynamically scoped
refinements worth it?
no.
This is what the core team decided right before Ruby 2.0.
-4-
refinements today
So we have a different versions of Refinements instead.
module StringExtensions
refine String do
def shout
upcase + "!"
end
end
end
module ModuleThatUsesTheRefinement
using StringExtensions
"hello".shout # => "HELLO!"
end
This stuff is the same…
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
C.class_eval do
"hello".shout # => NoMethodError
end
…but this doesn’t work.
lexical scope
class C
using StringExtensions
"hello".shout # => "HELLO!"
end
C.class_eval do
"hello".shout # => NoMethodError
end
No matter how you change the scope, Refinements *only* work in the lexical scope.
(almost) no confusion
def add(x, y)
x + y
end
SomeClass.class_eval do
add(1, 1) # => 2
end
SomeOtherClass.class_eval do
add(1, 1) # => 2
end
using FloatPointMath # refines Fixnum#+
add(1, 1) # => 2
(Note that the very last line might still surprise you, until you wrap your head around lexical scoping).
the three use cases again
But how do these new Refinements apply to the three main use cases of Monkeypatching?
describe Fixnum do
it("can be added") do
(2 + 2).should == 4
end
end
# => NoMethodError (undefined method 'it')
domain specific languages
This doesn’t work anymore.
class MyClass < ActiveRecord::Base
2.hours
end
# => NoMethodError (undefined method 'hours')
convenience methods
Neither does this.
class MyClass < ActiveRecord::Base
using ActiveSupport::CoreExtensions
2.hours # => 7200 seconds
end
convenience methods
(Unless I use using() in each and every class where I want the refinements - not very DRY).
module StringExtensions
refine String do
def length
super > 5 ? "long" : "short"
end
end
end
using StringExtensions
"War and Peace".length # => "long"
method wrappers
This one does work, thans to the way “super” works in Refinements.
•they don’t fix monkeypatches in general
•they still have weird corner cases
refinements today: the bad_
The bad of Lexically Scoped Refinements.
•they do fix some monkeypatching cases
•they don’t make the code confusing
•they don’t impact performance or security
•…and besides, they open the road for more
refinements today: the good
The good of Lexically Scoped Refinements.
-5-
a deep problem
describe Fixnum do
it "can be added" do
(2 + 2).should == 4
end
end
This code relies on multiple features that do not seem to make much sense (singleton classes, optional parentheses), but ended up being “abused” by the
community. It is hard to plan for this.
language design
is a deep problem
The point of this entire speech: we cannot plan. We need to experiment.
thank you
Buy this book. ;)

More Related Content

What's hot

Refactoring
RefactoringRefactoring
Refactoring
nkaluva
 
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 data structures
Python data structuresPython data structures
Python data structures
Harry Potter
 

What's hot (16)

Python quickstart for programmers: Python Kung Fu
Python quickstart for programmers: Python Kung FuPython quickstart for programmers: Python Kung Fu
Python quickstart for programmers: Python Kung Fu
 
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...
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
 
Refactoring
RefactoringRefactoring
Refactoring
 
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
 
PythonOOP
PythonOOPPythonOOP
PythonOOP
 
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
 
R Debugging
R DebuggingR Debugging
R Debugging
 
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...
 
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
 
Notes on assignment in r
Notes on assignment in rNotes on assignment in r
Notes on assignment in r
 
Unit vii wp ppt
Unit vii wp pptUnit vii wp ppt
Unit vii wp ppt
 
Python basics
Python basicsPython basics
Python basics
 
Python data structures
Python data structuresPython data structures
Python data structures
 
10 Recursion
10 Recursion10 Recursion
10 Recursion
 

Similar to Ruby Refinements: the Worst Feature You Ever Loved

Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
PatchSpace Ltd
 
cs3157-summer06-lab1
cs3157-summer06-lab1cs3157-summer06-lab1
cs3157-summer06-lab1
tutorialsruby
 
cs3157-summer06-lab1
cs3157-summer06-lab1cs3157-summer06-lab1
cs3157-summer06-lab1
tutorialsruby
 

Similar to Ruby Refinements: the Worst Feature You Ever Loved (20)

Test First Teaching
Test First TeachingTest First Teaching
Test First Teaching
 
Ruby Gotchas
Ruby GotchasRuby Gotchas
Ruby Gotchas
 
The Ring programming language version 1.8 book - Part 7 of 202
The Ring programming language version 1.8 book - Part 7 of 202The Ring programming language version 1.8 book - Part 7 of 202
The Ring programming language version 1.8 book - Part 7 of 202
 
Test First Teaching and the path to TDD
Test First Teaching and the path to TDDTest First Teaching and the path to TDD
Test First Teaching and the path to TDD
 
Erlang And ActorDB
Erlang And ActorDB Erlang And ActorDB
Erlang And ActorDB
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Elixir and OTP Apps introduction
Elixir and OTP Apps introductionElixir and OTP Apps introduction
Elixir and OTP Apps introduction
 
The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210
 
The Ring programming language version 1.9 book - Part 7 of 210
The Ring programming language version 1.9 book - Part 7 of 210The Ring programming language version 1.9 book - Part 7 of 210
The Ring programming language version 1.9 book - Part 7 of 210
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby Basics
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
 
00_Introduction to Java.ppt
00_Introduction to Java.ppt00_Introduction to Java.ppt
00_Introduction to Java.ppt
 
The Ring programming language version 1.5.3 book - Part 6 of 184
The Ring programming language version 1.5.3 book - Part 6 of 184The Ring programming language version 1.5.3 book - Part 6 of 184
The Ring programming language version 1.5.3 book - Part 6 of 184
 
Dutch PHP Conference 2013: Distilled
Dutch PHP Conference 2013: DistilledDutch PHP Conference 2013: Distilled
Dutch PHP Conference 2013: Distilled
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
 
Language supports it
Language supports itLanguage supports it
Language supports it
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
The Ring programming language version 1.5.4 book - Part 6 of 185
The Ring programming language version 1.5.4 book - Part 6 of 185The Ring programming language version 1.5.4 book - Part 6 of 185
The Ring programming language version 1.5.4 book - Part 6 of 185
 
cs3157-summer06-lab1
cs3157-summer06-lab1cs3157-summer06-lab1
cs3157-summer06-lab1
 
cs3157-summer06-lab1
cs3157-summer06-lab1cs3157-summer06-lab1
cs3157-summer06-lab1
 

Recently uploaded

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 

Recently uploaded (20)

tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 

Ruby Refinements: the Worst Feature You Ever Loved

Editor's Notes

  1. “Obvious” problems are those that you can solve yourself, if you have some time and knowledge.
  2. “Non-obvious” problems require more effort. You might not know how to solve them at first.
  3. “Deep” problems might not even have an optimal solution. You have to experiment.
  4. Let’s look at the problem that refinements are designed to solve.
  5. In Ruby, you can do this.
  6. Three of the most important use cases for monkeypatching.
  7. This example also shows why monkeypatches are dangerous: because they are global.
  8. This is what we want, and what Refinements are.
  9. Let’s look at Refinements, the way they were originally conceived.
  10. Refinement in a class/module. Only active in the marked area.
  11. Refinement at the top level. Only active in the marked area.
  12. …but will it work here?
  13. …or here?
  14. …or here?
  15. The original proposal (Dynamically Scoped Refinements) says yes, in all three cases.
  16. But people found potential problems with this.
  17. You need to look at the implementations to understand the interface.
  18. The interpreter also needs to do the same, so Refinements can slow down the entire interpreter.
  19. Less understanding potentially means less security.
  20. Some things might not work as you expect. (For example, the last line doesn’t work in irb).
  21. The good of Dynamically Scoped Refinements.
  22. The bad of Dynamically Scoped Refinements.
  23. This is what the core team decided right before Ruby 2.0.
  24. So we have a different versions of Refinements instead.
  25. This stuff is the same…
  26. …but this doesn’t work.
  27. No matter how you change the scope, Refinements *only* work in the lexical scope.
  28. (Note that the very last line might still surprise you, until you wrap your head around lexical scoping).
  29. But how do these new Refinements apply to the three main use cases of Monkeypatching?
  30. This doesn’t work anymore.
  31. Neither does this.
  32. (Unless I use using() in each and every class where I want the refinements - not very DRY).
  33. This one does work, thans to the way “super” works in Refinements.
  34. The bad of Lexically Scoped Refinements.
  35. The good of Lexically Scoped Refinements.
  36. This code relies on multiple features that do not seem to make much sense (singleton classes, optional parentheses), but ended up being “abused” by the community. It is hard to plan for this.
  37. The point of this entire speech: we cannot plan. We need to experiment.
  38. Buy this book. ;)