SlideShare a Scribd company logo
1 of 26
Photo by lucynieto http://www.flickr.com/photos/lucynieto/2299831355/
Patrones de diseño
(en ruby)
Ignacio (Nacho) Facello
@nachof
nacho@nucleartesuji.com
Photo by lucynieto http://www.flickr.com/photos/lucynieto/2299831355/
Patrones de diseño
(en ruby)
Ignacio (Nacho) Facello
@nachof
nacho@nucleartesuji.com
Qué son patrones de diseño?
● Un patrón de diseño es una solución general
reutilizable a un problema de común ocurrencia
en el diseño de software (Wikipedia)
● Concepto originalmente usado en arquitectura
(Christopher Alexander)
● Popularizado en el libro Design Patterns:
Elements of Reusable Object-Oriented
Software, popularmente conocido como GoF
(Gang of Four), de Erich Gamma, Richard
Helm, Ralph Johnson, y John Vlissides.
Para qué sirven?
● Conocer una solución para un problema dado
es útil cuando uno se enfrenta a ese problema.
● Nos dan un lenguaje común.
● Suelen resultar en un buen diseño
Todo lo que sé de
patrones lo aprendí
jugando go
Joseki
El mismo joseki...
… en diferentes contextos.
Cuando no sirven...
● Que algo sea un patrón no quiere decir que sea
adecuado.
● El contexto lo es todo.
Lo importante: elegir la herramienta
adecuada
Photo by jannem http://www.flickr.com/photos/jannem/3312116875/
Algunos ejemplos de
patrones en Ruby
Singleton
require 'singleton' # From stdlib
class SingletonExample
include Singleton
end
one = SingletonExample.instance
two = SingletonExample.instance
puts one == two #=> true
Observer
require 'observer' # From stdlib
class Car
include Observable
def initialize
@fuel = 100
@speed = 0
end
def run
while @fuel > 0 do
@speed += 1
@fuel -= 1
changed
notify_observers (@speed,
@fuel)
end
end
end
class SpeedWarner
def initialize(car,
speed_limit)
@limit = speed_limit
car.add_observer(self)
end
def update(speed, fuel)
puts "Too fast!" if speed >
@limit
end
end
car = Car.new
SpeedWarner.new(car, 70)
FuelWarner.new(car, 10)
car.run
State
require 'state_pattern' # Gem by
@dcadenas
# http://github.com/dcadenas/state_pattern
class Stop < StatePattern::State
def next
sleep 3
transition_to (Go)
end
def color
"Red"
end
end
class Go < StatePattern::State
def next
sleep 2
transition_to (Caution)
end
def color
"Green"
end
end
class Caution < StatePattern::State
def next
sleep 1
transition_to (Stop)
end
def color
"Amber"
end
end
class TrafficSemaphore
include StatePattern
set_initial_state Stop
end
semaphore = TrafficSemaphore.new
loop do
puts semaphore.color
semaphore.next
end
Adapter
require 'forwardable'
class LegacyClassA
def some_method(a, b)
puts "#{a}, #{b} (old A)"
end
end
class LegacyClassB
def do_something(b, a)
puts "#{a}, #{b} (old B)"
end
end
class AdapterA
extend Forwardable
def initialize(adaptee)
@adaptee = adaptee
end
def_delegator :@adaptee,
:some_method, :action
end
class AdapterB
def initialize(adaptee)
@adaptee = adaptee
end
def action(a, b)
@adaptee.do_something(b, a)
end
end
adapted_a =
AdapterA.new(LegacyClassA.new)
adapted_b =
AdapterB.new(LegacyClassB.new)
[adapted_a, adapted_b].each { |
adapted| adapted.action("Hello",
"World") }
Iterator
class ArrayIterator
def initialize(array)
@array = array
@index = 0
end
def first
@index = 0
end
def next
@index += 1
end
def current
@array [@index]
end
def over?
@index >= @array.size
end
end
list = [1,2,3,4]
iterator = ArrayIterator.new(list)
while (!iterator.over?) do
puts iterator.current
iterator.next
end
Iterator
class ArrayIterator
def initialize(array)
@array = array
@index = 0
end
def first
@index = 0
end
def next
@index += 1
end
def current
@array [@index]
end
def over?
@index >= @array.size
end
end
list = [1,2,3,4]
iterator = ArrayIterator.new(list)
while (!iterator.over?) do
puts iterator.current
iterator.next
end
Mucho más sencillo...
list = [1,2,3,4]
list.each do |item|
puts item
end
Otras formas de iterar
list = [1,2,3,4]
list.each do |item|
puts item
end
list.map { |item| item * 2 } #=> [3,4,5,6]
list.any? { |item| item == 2 } #=> true
list.select { |item| item > 2 } #=> [3,4]
list.detect { |item| item > 2 } #=> 3
Strategy
require 'forwardable'
class Caveman
extend Forwardable
attr_accessor :strategy
def initialize(strategy =
DefaultStrategy.new)
@strategy = strategy
end
def_delegator :@strategy, :survive
def normal_day
wake_up
survive
go_to_sleep
end
def wake_up
puts "Waking up"
end
def go_to_sleep
puts "Sleep now"
end
end
class DefaultStrategy
def survive
puts "Hide from tigers"
end
end
class AggressiveStrategy
def survive
puts "Grab spear, hunt tigers"
end
end
class ConfusedStrategy
def survive
puts "Grab tiger, hunt spears"
end
end
og = Caveman.new
og.normal_day
og.strategy = AggressiveStrategy.new
og.normal_day
Strategy (con lambdas)
class Caveman
attr_accessor :strategy
def initialize(strategy = lambda { puts "Hide from tiger" })
@strategy = strategy
end
def normal_day
wake_up
survive
go_to_sleep
end
def survive
@strategy.call
end
def wake_up
puts "Waking up"
end
def go_to_sleep
puts "Sleep now"
end
end
og = Caveman.new
og.normal_day
og.strategy = lambda { puts "Grab spear, hunt tiger" }
og.normal_day
Algunos usos
● Rails: Model-View-Controller
● ActiveRecord::Observer: Observer
● Array#sort: Strategy
Algunos comentarios finales
● Stdlib y gemas son útiles
● Memorizarse los patrones y usarlos a cada
oportunidad no ayuda.
● Entender sus consecuencias, y su porqué, sí
sirve.
● “There may be a dozen different ways to
implement a [given pattern] - it doesn't have to
be done exactly like the GoF book or some web
page.” Paul Wheaton
(http://www.javaranch.com/patterns/)
Gracias :-)

More Related Content

Similar to Patrones de diseño (en Ruby) — RubyConf Uruguay 2010

From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scalatod esking
 
ScalaDays 2013 Keynote Speech by Martin Odersky
ScalaDays 2013 Keynote Speech by Martin OderskyScalaDays 2013 Keynote Speech by Martin Odersky
ScalaDays 2013 Keynote Speech by Martin OderskyTypesafe
 
Object Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonPython Ireland
 
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...Databricks
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable LispAstrails
 
Design Patterns By Sisimon Soman
Design Patterns By Sisimon SomanDesign Patterns By Sisimon Soman
Design Patterns By Sisimon SomanSisimon Soman
 
Origins of Elixir programming language
Origins of Elixir programming languageOrigins of Elixir programming language
Origins of Elixir programming languagePivorak MeetUp
 
Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python Jean Carlo Machado
 
Ejercicios de estilo en la programación
Ejercicios de estilo en la programaciónEjercicios de estilo en la programación
Ejercicios de estilo en la programaciónSoftware Guru
 
Yin Yangs of Software Development
Yin Yangs of Software DevelopmentYin Yangs of Software Development
Yin Yangs of Software DevelopmentNaveenkumar Muguda
 
Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insAndrew Dupont
 
Design patterns - Using Ruby
Design patterns - Using RubyDesign patterns - Using Ruby
Design patterns - Using RubyShifa Khan
 
Windy City DB - Recommendation Engine with Neo4j
Windy City DB - Recommendation Engine with Neo4jWindy City DB - Recommendation Engine with Neo4j
Windy City DB - Recommendation Engine with Neo4jMax De Marzi
 
PyData NYC 2019
PyData NYC 2019PyData NYC 2019
PyData NYC 2019Li Jin
 
Blocks by Lachs Cox
Blocks by Lachs CoxBlocks by Lachs Cox
Blocks by Lachs Coxlachie
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversBrian Gesiak
 

Similar to Patrones de diseño (en Ruby) — RubyConf Uruguay 2010 (20)

Ruby tricks2
Ruby tricks2Ruby tricks2
Ruby tricks2
 
From Ruby to Scala
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scala
 
ScalaDays 2013 Keynote Speech by Martin Odersky
ScalaDays 2013 Keynote Speech by Martin OderskyScalaDays 2013 Keynote Speech by Martin Odersky
ScalaDays 2013 Keynote Speech by Martin Odersky
 
The Joy Of Ruby
The Joy Of RubyThe Joy Of Ruby
The Joy Of Ruby
 
Object Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in Python
 
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...
Ray: A Cluster Computing Engine for Reinforcement Learning Applications with ...
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable Lisp
 
Design Patterns By Sisimon Soman
Design Patterns By Sisimon SomanDesign Patterns By Sisimon Soman
Design Patterns By Sisimon Soman
 
Origins of Elixir programming language
Origins of Elixir programming languageOrigins of Elixir programming language
Origins of Elixir programming language
 
Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python
 
Lab 4
Lab 4Lab 4
Lab 4
 
Ejercicios de estilo en la programación
Ejercicios de estilo en la programaciónEjercicios de estilo en la programación
Ejercicios de estilo en la programación
 
Yin Yangs of Software Development
Yin Yangs of Software DevelopmentYin Yangs of Software Development
Yin Yangs of Software Development
 
Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-ins
 
Design patterns - Using Ruby
Design patterns - Using RubyDesign patterns - Using Ruby
Design patterns - Using Ruby
 
firststeps
firststepsfirststeps
firststeps
 
Windy City DB - Recommendation Engine with Neo4j
Windy City DB - Recommendation Engine with Neo4jWindy City DB - Recommendation Engine with Neo4j
Windy City DB - Recommendation Engine with Neo4j
 
PyData NYC 2019
PyData NYC 2019PyData NYC 2019
PyData NYC 2019
 
Blocks by Lachs Cox
Blocks by Lachs CoxBlocks by Lachs Cox
Blocks by Lachs Cox
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
 

Recently uploaded

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 

Recently uploaded (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 

Patrones de diseño (en Ruby) — RubyConf Uruguay 2010

  • 1. Photo by lucynieto http://www.flickr.com/photos/lucynieto/2299831355/ Patrones de diseño (en ruby) Ignacio (Nacho) Facello @nachof nacho@nucleartesuji.com
  • 2.
  • 3. Photo by lucynieto http://www.flickr.com/photos/lucynieto/2299831355/ Patrones de diseño (en ruby) Ignacio (Nacho) Facello @nachof nacho@nucleartesuji.com
  • 4. Qué son patrones de diseño? ● Un patrón de diseño es una solución general reutilizable a un problema de común ocurrencia en el diseño de software (Wikipedia) ● Concepto originalmente usado en arquitectura (Christopher Alexander) ● Popularizado en el libro Design Patterns: Elements of Reusable Object-Oriented Software, popularmente conocido como GoF (Gang of Four), de Erich Gamma, Richard Helm, Ralph Johnson, y John Vlissides.
  • 5. Para qué sirven? ● Conocer una solución para un problema dado es útil cuando uno se enfrenta a ese problema. ● Nos dan un lenguaje común. ● Suelen resultar en un buen diseño
  • 6. Todo lo que sé de patrones lo aprendí jugando go
  • 9. … en diferentes contextos.
  • 10. Cuando no sirven... ● Que algo sea un patrón no quiere decir que sea adecuado. ● El contexto lo es todo.
  • 11. Lo importante: elegir la herramienta adecuada Photo by jannem http://www.flickr.com/photos/jannem/3312116875/
  • 13. Singleton require 'singleton' # From stdlib class SingletonExample include Singleton end one = SingletonExample.instance two = SingletonExample.instance puts one == two #=> true
  • 14. Observer require 'observer' # From stdlib class Car include Observable def initialize @fuel = 100 @speed = 0 end def run while @fuel > 0 do @speed += 1 @fuel -= 1 changed notify_observers (@speed, @fuel) end end end class SpeedWarner def initialize(car, speed_limit) @limit = speed_limit car.add_observer(self) end def update(speed, fuel) puts "Too fast!" if speed > @limit end end car = Car.new SpeedWarner.new(car, 70) FuelWarner.new(car, 10) car.run
  • 15. State require 'state_pattern' # Gem by @dcadenas # http://github.com/dcadenas/state_pattern class Stop < StatePattern::State def next sleep 3 transition_to (Go) end def color "Red" end end class Go < StatePattern::State def next sleep 2 transition_to (Caution) end def color "Green" end end class Caution < StatePattern::State def next sleep 1 transition_to (Stop) end def color "Amber" end end class TrafficSemaphore include StatePattern set_initial_state Stop end semaphore = TrafficSemaphore.new loop do puts semaphore.color semaphore.next end
  • 16. Adapter require 'forwardable' class LegacyClassA def some_method(a, b) puts "#{a}, #{b} (old A)" end end class LegacyClassB def do_something(b, a) puts "#{a}, #{b} (old B)" end end class AdapterA extend Forwardable def initialize(adaptee) @adaptee = adaptee end def_delegator :@adaptee, :some_method, :action end class AdapterB def initialize(adaptee) @adaptee = adaptee end def action(a, b) @adaptee.do_something(b, a) end end adapted_a = AdapterA.new(LegacyClassA.new) adapted_b = AdapterB.new(LegacyClassB.new) [adapted_a, adapted_b].each { | adapted| adapted.action("Hello", "World") }
  • 17. Iterator class ArrayIterator def initialize(array) @array = array @index = 0 end def first @index = 0 end def next @index += 1 end def current @array [@index] end def over? @index >= @array.size end end list = [1,2,3,4] iterator = ArrayIterator.new(list) while (!iterator.over?) do puts iterator.current iterator.next end
  • 18. Iterator class ArrayIterator def initialize(array) @array = array @index = 0 end def first @index = 0 end def next @index += 1 end def current @array [@index] end def over? @index >= @array.size end end list = [1,2,3,4] iterator = ArrayIterator.new(list) while (!iterator.over?) do puts iterator.current iterator.next end
  • 19. Mucho más sencillo... list = [1,2,3,4] list.each do |item| puts item end
  • 20. Otras formas de iterar list = [1,2,3,4] list.each do |item| puts item end list.map { |item| item * 2 } #=> [3,4,5,6] list.any? { |item| item == 2 } #=> true list.select { |item| item > 2 } #=> [3,4] list.detect { |item| item > 2 } #=> 3
  • 21. Strategy require 'forwardable' class Caveman extend Forwardable attr_accessor :strategy def initialize(strategy = DefaultStrategy.new) @strategy = strategy end def_delegator :@strategy, :survive def normal_day wake_up survive go_to_sleep end def wake_up puts "Waking up" end def go_to_sleep puts "Sleep now" end end class DefaultStrategy def survive puts "Hide from tigers" end end class AggressiveStrategy def survive puts "Grab spear, hunt tigers" end end class ConfusedStrategy def survive puts "Grab tiger, hunt spears" end end og = Caveman.new og.normal_day og.strategy = AggressiveStrategy.new og.normal_day
  • 22. Strategy (con lambdas) class Caveman attr_accessor :strategy def initialize(strategy = lambda { puts "Hide from tiger" }) @strategy = strategy end def normal_day wake_up survive go_to_sleep end def survive @strategy.call end def wake_up puts "Waking up" end def go_to_sleep puts "Sleep now" end end og = Caveman.new og.normal_day og.strategy = lambda { puts "Grab spear, hunt tiger" } og.normal_day
  • 23. Algunos usos ● Rails: Model-View-Controller ● ActiveRecord::Observer: Observer ● Array#sort: Strategy
  • 24. Algunos comentarios finales ● Stdlib y gemas son útiles ● Memorizarse los patrones y usarlos a cada oportunidad no ayuda. ● Entender sus consecuencias, y su porqué, sí sirve. ● “There may be a dozen different ways to implement a [given pattern] - it doesn't have to be done exactly like the GoF book or some web page.” Paul Wheaton (http://www.javaranch.com/patterns/)
  • 25.

Editor's Notes

  1. Presentación De qué voy a hablar
  2. Presentación De qué voy a hablar
  3. Seguir slide, es sencilla
  4. Solución conocida a problema dado Lenguaje común, ejemplo observer “Mal” ejemplo: goto, o alguna otra cosa Buen diseño, siempre y cuando estemos hablando del contexto adecuado
  5. Va a ser una metáfora visual
  6. Secuencia de jugadas con un resultado parejo para ambos jugadores En este caso, blanco esquina, negro afuera
  7. Izquierda: negro trabaja bien Derecha: la pared de negro se enfrenta a blanco que lo neutraliza
  8. Lo más importante: el contexto.
  9. Es decir, elegir la herramienta adecuada para el problema actual es imprescindible
  10. Uno de los patrones más odiados. Tiene algunos casos de uso El ejemplo: porque el soporte está en stdlib — se encarga de temas de concurrencia y múltiples threads
  11. Permite que un objeto notifique a otros sobre cambios en su estado También soporte en stdlib Requerir &amp;apos;observer&amp;apos; En la clase observable, requerir Observable El método add_observer (en el initializer de los observers) agrega los observers al observable El método notify_observers en el observable llama al update de los observers, con los mismos argumentos. Pero sólo si antes llamamos a changed para avisarle
  12. Permite a un objeto cambiar su comportamiento de acuerdo a su estado interno (sin cambiar la interfaz) Hay muchas librerías que ayudan con State Elegí esta porque me parece clara Hasta le robé el ejemplo de código del readme Cada estado hereda de StatePattern::State El objeto incluye StatePattern Y define el estado inicial transition_to cambia el objeto estado Los métodos color y next son implícitamente delegados al objeto estado
  13. Hablando de delegar, hay varios patrones que usan delegación, no sólo State. Adapter, por ejemplo. Nos permite adaptar la interfaz de varias clases incompatibles a una misma interfaz que podemos usar. Para eso, es útil Forwardable En el caso de AdapterA, extiende Forwardable, y luego usa def_delegator. En el caso de AdapterB, no se puede, porque el orden de los parámetros es diferente
  14. Iterator nos permite recorrer una lista de objetos, como por ejemplo un array, para trabajar con ellos Implementación casi directa del GoF Para alguien que venga de Java, va a ser algo bastante conocido
  15. Pero en ese caso estás haciendo Java, no Ruby
  16. En Ruby hay formas más expresivas de lograr lo mismo Tenemos each para iterar sobre elementos
  17. Cuando iteramos con diferentes objetivos, es más expresivo iterar con métodos que expliquen qué es lo que queremos lograr Todos estos métodos están definidos en Enumerable Si tuviéramos otra estructura sobre la que iterar, con sólo implementar each e incluír el módulo Enumerable Ayer Aaron Patterson mostró un par de implementaciones para un árbol
  18. Permite cambiar la forma en la que un objeto se comporta Ejemplo medio clásico, con distintos objetos para cada Strategy Otra opción, tal vez más ruby, sería incluír módulos para cada Strategy diferente
  19. Me gusta más esta manera, parece más ruby
  20. Hay muchos usos de patrones que usamos todos los días, muchos que tenemos tan integrados que casi no nos damos cuenta Estos son sólo algunos ejemplos, hay muchos más si uno quiere buscar