SlideShare a Scribd company logo
1 of 97
Refatorando Ruby
Técnicas de Orientação a Objetos e Design Patterns
         Aplicados a Linguagens Dinâmicas




                  Cássio Marques
              Ruby e Rails no Mundo Real 2010
cassiomarques.wordpress.com

     @cassiomarques

   cassiommc@gmail.com
http://www.flickr.com/photos/docman/




  Refatoração
Motivações
Muitos programadores
  usando Ruby não
  sabem usar OO
“Raciocínio estático”
Linguagem nova, mas
   hábitos antigos
Organização
Modularizar o código
Facilitar manutenção
Facilitar compreensão
do código para novos
  desenvolvedores
Design Patterns
Motivações
Ajudar o Ruby a ser
   “Enterprise”
Patterns implementados X Enterprisy
YAGNI
Um exemplo simples...
 1   class Bhaskara
 2     def solve(a, b, c)
 3       # Calcula o delta
 4       d = b ** 2 - 4 * a * c
 5
 6       if d < 0
 7         puts 'Raízes complexas - Não sei resolver!'
 8       else
 9         # calculando raízes
10         r1 = (-b + Math.sqrt(d))/(2.0 * a)
11         r2 = (-b - Math.sqrt(d))/(2.0 * a)
12
13         # imprimindo resultados
14         puts "Raiz 1: #{r1}"
15         puts "Raiz 2: #{r2}"
16       end
17     end
18   end
1 class Bhaskara  
2 end
1   class Bhaskara
2     def initialize(a, b, c)
3       @a, @b, @c = a, b, c
4     end
5   end
 1   class Bhaskara
 2     def initialize(a, b, c)
 3       @a, @b, @c = a, b, c
 4     end
 5
 6     private
 7     def delta
 8       @b ** 2 - 4 * @a * @c    
 9     end
10
11     def solve
12       @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a)
13       @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a)
14     end
15   end
 1   class Bhaskara
 2     def initialize(a, b, c)
 3       @a, @b, @c = a, b, c
 4     end
 5
 6     def print_results
 7       if delta < 0
 8         puts 'Raízes complexas - Não sei resolver!'
 9       else
10         solve
11         puts "Raiz 1: #{@r1}"
12         puts "Raiz 2: #{@r2}"
13       end
14     end
15
16     private
17     def delta
18       @b ** 2 - 4 * @a * @c    
19     end
20
21     def solve
22       @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a)
23       @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a)
24     end
25   end
 1   class Bhaskara
 2     def initialize(a, b, c)
 3       @a, @b, @c = a, b, c
 4     end
 5
 6     def print_results
 7       delta < 0 ? print_complex_results : print_real_results
 8     end
 9
10     private
11     def delta
12       @b ** 2 - 4 * @a * @c    
13     end
14
15     def solve
16       @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a)
17       @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a)
18     end
19
20     def print_real_results
21       solve
22       puts "Raiz 1: #{@r1}"
23       puts "Raiz 2: #{@r2}"
24     end
25
26     def print_complex_results
27       puts 'Raízes complexas - Não sei resolver!'
28     end
29   end
O que eu preciso para
     refatorar?
TESTES
Mantenha seus métodos
      pequenos




                http://www.flickr.com/photos/davidden/
 1   class ShoppingCart
 2     def total_value
 3       total = 0
 4       for item in @items
 5         sub_total = item.value * item.quantity
 6         if item.quantity > 3
 7           sub_total *= 0.90
 8         elsif item.quantity > 6
 9           sub_total *= 0.85
10         elsif item.quantiy > 9
11           sub_total *= 0.80
12         end
13         total += sub_total
14       end
15       total
16     end
17   end
 1   # - Elimina variáveis temporárias em favor de métodos
 2   class ShoppingCart
 3     def total_value
 4       total = 0
 5       for item in @items
 6         total += if item.quantity > 3
 7           sub_total(item) * 0.90
 8         elsif item.quantity > 6
 9           sub_total(item) * 0.85
10         elsif item.quantiy > 9
11           sub_total(item) * 0.80
12         end
14       end
15       total
16     end
17
18     def sub_total(item)
19       item.value * item.quantity
20     end
21   end
22
 1   # - Método usa apenas atributos de outro objeto
 2   #  => Mover!
 3   class ShoppingCart
 4     def total_value
 5       total = 0
 6       for item in @items
 7         total += if item.quantity > 3
 8           item.total_value * 0.90
 9         elsif item.quantity > 6
10           item_total_value * 0.85
11         elsif item.quantiy > 9
12           item.total_value = 0.80
13         end       
14       end
15       total
16     end
17   end
18
19   class Item
20     def total_value
21       @value * @quantity
22     end
23   end
 1   # - Método fazendo coisa demais
 2   # => Extrair!
 3   class ShoppingCart
 4     def total_value
 5       total = 0
 6       for item in @items
 7         total += item.total_value * discount(item.quantity)
 8       end
 9       total
10     end
11
12     def discount(quantity)
13       case quantity
14       when (1..2); 1.00
15       when (3..5); 0.90
16       when (6..8); 0.85
17       else 0.80    
18       end
19     end
20   end
 1   # - Use Ruby!
 2   class ShoppingCart
 3     def total_value
 4       items.inject(0.0) { |sum, item| 
 5         sum += item.total_value * discount(item.quantity)
 6       }
 7     end
 8
 9     def discount(quantity)
10       case quantity
11       when (1..2); 1.00
12       when (3..5); 0.90
13       when (6..8); 0.85
14       else 0.80    
15       end
16     end
17   end
Faça objetos se comportarem
       como coleções




                   http://www.flickr.com/photos/deepsignal/366774303/sizes/l/
 1   class Library
 2     def search_book_by_title(title)
 3       @books.select { |book| book.title == title }
 4     end
 5
 6     def search_book_by_author(author)
 7       @books.select { |book| book.author == author }
 8     end
 9
10     def sort_by_title
11       @books.sort_by { |book| book.title }
12     end
13
14     def authors
15       @books.map { |book| book.author }
16     end
17
18     # ...
19   end
 1   class Library
 2     include Enumerable
 3
 4     def each
 5       @books.each { |book| yield book }
 6     end
 7   end
 8
 9   library.each { |book| ... }
10   library.inject { |book| ... }
11   library.map { |book| ... }
12   library.sort { |book| ... }
13   # ...
Dê nomes aos parâmetros
           dos métodos




                 http://www.flickr.com/photos/giantginkgo/
 1   class Dialog
 2     def initialize(height, width, name, title)
 3       @height = height
 4       @width  = width
 5       @name   = name
 6       @title  = title
 7     end
 8   end
 9
10   dialog = Dialog.new 200, 400, 'dialog1', 'A Dialog'
 1   class Dialog
 2     def initialize(options)
 3       @height = options[:height]
 4       @width  = options[:width]
 5       @name   = options[:name]
 6       @title  = options[:title]
 7     end
 8   end
 9
10   dialog = Dialog.new(
11     :height => 200,
12     :width  => 400,
13     :name   => 'dialog1',
14     :title  => 'A Dialog'
15   )
Anotações




http://www.flickr.com/photos/matski_98/
 1   class Person
 2     def state=(state)
 3       unless [:sick, :healthy].include?(state)
 4         raise ArgumentError, "unknown state: #{state}" 
 5       end
 6       @state = state
 7     end
 8   end
 9
10   class Vehicle
11     def state=(state)
12       unless [:parked, :running].include?(state)
13         raise ArgumentError, "unknown state: #{state}" 
14       end
15       @state = state
16     end
17   end
 1   module HasStates
 2     def has_states(*args)
 3       define_method :state= do |new_state|
 4         unless args.include?(new_state)
 5           raise ArgumentError, "unknown state: #{state}" 
 6         end
 7         @state = new_state
 8       end
 9     end
10   end
 1   class Person
 2     extend HasStates
 3
 4     has_states :sick, :healthy
 5   end
 6
 7   class Vehicle
 8     extend HasStates
 9
10     has_states :parked, :running
11   end
12
13   Object.extend HasStates
Uma classe não deve
realizar trabalhos que
 não lhe pertencem...
1   class Person
2     attr_accessor :telephone_number, :telephone_area_code
3
4     def formatted_telephone
5       "(#{telephone_area_code}) #{telephone_number}"
6     end
7   end
 1   class Person
 2     def initialize
 3       @telephone_number = TelephoneNumber.new
 4     end
 5   end
 6
 7   class TelephoneNumber
 8     attr_accessor :area_code, :number
 9
10     def formatted
11       "(#{area_code}) #{number}"
12     end
13   end
Delegue, delegue, delegue...
 1   class Queue
 2     def initialize
 3       @queue = []
 4     end
 5
 6     def enqueue(element)
 7       @queue.unshift element    
 8     end
 9
10     def dequeue
11       @queue.pop
12     end
13   end
O Ruby pode dar uma
     ajudinha...
 1   require 'forwardable'
 2
 3   class Queue
 4     extend Forwardable
 5
 6     def initialize
 7       @queue = []
 8     end
 9
10     def_delegator :@queue, :unshift, :enqueue
11     def_delegator :@queue, :pop, :dequeue
12   end
Não exponha o interior de
seus objetos sem necessidade




                         http://www.flickr.com/photos/mwichary/
 1   class Room
 2     attr_reader :air_conditioner
 3   end
 4
 5   class AirConditioner
 6     attr_reader :sensor
 7   end
 8
 9   class TemperatureSensor
10     def temperature
11       #...
12     end
13   end
14
15   if room.air_conditioner.sensor.temperature > 28
16     room.air_conditioner.on
17   end
 1   class Room
 2     attr_reader :air_conditioner
 3
 4     def temperature
 5       air_conditioner.sensor.temperature
 6     end
 7   end
 8
 9   if room.temperature > 28
10     room.air_conditioner.on
11   end
Substitua números
mágicos por constantes




http://decluttr.com/4524127771_white
1   class Circle
2     def area
3       3.14159265 * (r ** 2)
4     end
5   end
1   class Circle
2     PI = 3.14159265 
3
4     def area
5       PI * (r ** 2)
6     end
7   end
Encapsule coleções de
                                                        objetos




http://www.flickr.com/photos/eagleglide/
 1   class Cart
 2     attr_accessor :products
 3   end
 4
 5   class Product
 6     attr_reader :value, :name
 7
 8     def initialize(name, value)
 9       @name, @value = name, value
10     end
11   end
1   products = []
2   products << Product.new('Camiseta', 35.00)
3   products << Product.new('Bermuda', 38.00)
4   products << Product.new('Boné', 20.00)
5   cart = Cart.new
6   cart.products = products
7   cart.products.pop # => alterei o estado do carrinho
 1   class Cart
 2     def initialize
 3       @products = []
 4     end
 5
 6     def add_product(product)
 7       @products << product    
 8     end
 9
10     def remove_product(product)
11       @products.delete product
12     end
13   end
14
15   cart = Cart.new
16   cart.add_product(Product.new('Camiseta', 35.00))
Substitua condicionais por
             polimorfismo




                   http://www.flickr.com/photos/randyread/
 1   class Tax
 2     def initialize(type, value)
 3       @type = type    
 4       @value = value
 5     end
 6
 7     def retained_value
 8       case @type
 9       when :irpj;   @value * 0.015
10       when :pis;    @value * 0.0065
11       when :cofins; @value * 0.030
12       when :iss;    0.0
13       end
14     end
15
16     def due_value
17       case @type
18       when :irpj;   @value * 0.033
19       when :pis;    0.0
20       when :cofins; 0.0
21       when :iss;    @value * 0.02
22       end
23     end
24   end
 1   module Tax
 2     def due_value
 3       @due_rate * @value    
 4     end
 5
 6     def retained_value
 7       @retained_rate * @value
 8     end
 9   end
10
11   class IrpjTax
12     include Tax
13
14     def initialize(value)
15       @value         = value
16       @due_rate      = 0.033
17       @retained_rate = 0.015
18     end
19   end
20
21   # o mesmo para as demais classes...
 1   class Invoice
 2     def initialize(value)
 3       @value = value
 4       create_taxes
 5     end
 6
 7     def add_tax(tax)
 8       @taxes << tax
 9     end
10     
11     def total_taxes_value
12       @taxes.inject(0.0) { |sum, tax|
13         sum += tax.due_value + tax.retained_value
14       }
15     end
16
17     private
18     def create_taxes
19       @taxes = []
20       @taxes << IrpjTax.new(@value)
21       @taxes << PisTax.new(@value)
22       @taxes << CofinsTax.new(@value)
23       @taxes << IssTax.new(@value)
24     end
25   end
26
27   invoice = Invoice.new 1400.00
28   puts invoice.total_taxes_value
Simplifique expressões
     condicionais
1 if product.release_date < 3.months.ago || quantity > 100
2   self.value *= 0.90
3 end
 1   if elegible_for_discount?
 2     self.value *= 0.90
 3   end
 4
 5   def elegible_for_discount?
 6     old? && great_quantity?
 7   end
 8
 9   def old?
10     product.release_date < 3.months.ago
11   end
12
13   def great_quantity?
14     quantity > 100
15   end
http://www.flickr.com/photos/jeff_oliver/




                                                 Mas uma expressão
                                                condicional pode ser
                                           melhor que ifs aninhados...
1   if age > 40
2     if gender == :male
3       if last_visit > 1.month.ago
4         # ...
5       end
6     end
7   end
1   if age > 40 && gender == :male && last_visit > 1.month
2     # ...
3   end
4
5   # e a partir daqui podemos extrair as condições para
6   # métodos...
Às vezes faz mais
sentido juntar do que
      separar...
1   class Bicycle
2     def press_front_brake
3       brakes[:front].press
4     end
5
6     def press_rear_brake
7       brakes[:rear].press
8     end
9   end
1   class Bicycle
2     def press_brake(brake)
3       brakes[brake].press
4     end
5   end
Verifique se a mensagem
                                         pode ser enviada




http://www.flickr.com/photos/funtik/
1   def do_something(target)
2     target.prepare rescue nil
3     target.explode
4   end
1   def do_something(target)
2     target.prepare if target.respond_to? :prepare
3     target.explode
4   end
Herança
 1   class CdPlayer     1   class TapeDeck
 2     def turn_on      2     def turn_on
 3       @on = true     3       @on = true
 4     end              4     end
 5                      5
 6     def turn_off     6     def turn_off
 7       @on = false    7       @on = false
 8     end              8     end
 9                      9
10     def play        10     def play
11       play_disc     11       play_tape
12     end             12     end
13   end               13   end
 1   class AudioDevice
 2     def turn_on
 3       @on = true
 4     end
 5
 6     def turn_off
 7       @on = false
 8     end
 9   end
10
11   class CdPlayer < AudioDevice
12     def play
13       play_disk
14     end
15   end
16
17   class TapeDeck < AudioDevice
18     def play
19       play_tape
20     end
21   end
Strategy
 1   class Text
 2     attr_reader :contents
 3
 4     def left_aligned_format
 5       # ...
 6     end
 7
 8     def right_aligned_format
 9       # ...
10     end
11
12     def justified_format
13       # ...
14     end
15   end
 1   class LeftAlignedFormatter
 2     def format(context)
 3       align_left context.contents
 4     end
 5   end
 6
 7   class RightAlignedFormatter
 8     def format(context)
 9       align_right context.contents
10     end
11   end
12
13   class RightJustifiedFormatter 
14     def format(context)
15       justify context.contents
16     end
17   end
 1   class Text
 2     attr_reader :contents
 3     attr_accessor :formatter
 4
 5     def initialize(contents, formatter)
 6       @contents, @formatter = contents, formatter
 7     end
 8
 9     def format
10       @formatter.format self
11     end
12   end
Blocos, ao resgate!




http://www.flickr.com/photos/bekahstargazing/
 1   class Text
 2     attr_reader :contents
 3     attr_accessor :formatter
 4
 5     def initialize(contents, &formatter)
 6       @contents, @formatter = contents, formatter
 7     end
 8
 9     def format
10       @formatter.call self
11     end
12   end
13
14   left_aligned_text = Text.new 'some text' do |context|
15     align_left context.contents
16   end
Use quando você precisar
 alterar o algorítmo em
   tempo de execução
http://www.flickr.com/photos/micahdowty/
 1   class Document
 2     def change_text_color(color)
 3       @text.color = color
 4     end
 5
 6     def change_background_color(color)
 7       @text.background_color = color    
 8     end
 9
10     def change_font_size(size)
11       @text.font_size = size    
12     end
13
14     def change_font(font)
15       @text.font = font
16     end
17   end
ctrl-z ?
 1   class Command
 2     attr_reader :description
 3
 4     def initialize(description)
 5       @description = description  
                                     
 6     end
 7   end
 1   class ChangeTextColorCommand < Command
 2     def initialize(target)
 3       super("Altera a cor do texto")    
 4       @target = target
 5     end
 6
 7     def execute(color)
 8       @old_color = @target.text.color
 9       @target.text.color = color
10     end  
11
12     def unexecute
13       @target.text.color = @old_color if @old_color
14     end
15   end
 1   class Document
 2     def initialize
 3       @commands = []
 4     end
 5
 6     def change_text_color(color)
 7       run_command ChangeTextColorCommand.new(self), color
 8     end
 9
10     def change_font(font)
11       run_command ChangeFontCommand.new(self), font
12     end
13
14     def undo_last_action
15       @commands.pop.unexecute unless @commands.empty?
16     end
17
18     private
19     def run_command(command, param)
20       command.execute param
21       @commands << command
22     end
23   end
Use quando você precisar
realizar tarefas específicas e
 mantê-las em um registro
Proxy
 1   class Task 
 2     def initialize(creator)
 3       @creator = creator
 4     end
 5
 6     def owner=(owner)
 7       @owner = owner    
 8     end
 9
10     def add_comment(comment)
11       @comments << comment
12     end
13
14     def update_description(new_description)
15       @description = description
16     end
17
18     def close
19       @status = :closed
20     end
21   end
 1   class TaskProtectionProxy
 2     def initialize(target)
 3       @target = target    
 4     end
 5
 6     def owner=(owner)
 7       check_permissions :owner=
 8       @owner = owner    
 9     end
10
11     def add_comment(comment)    
12       check_permissions :add_comment
13       @comments << comment
14     end
15
16     # ...
17
18     private
19     def check_permissions(what)
20       unless can_do?(current_user, what)
21         raise 'Acesso negado!' 
22       end
23     end
24   end
 1   class TaskProtectionProxy
 2     def initialize(target)
 3       @target = target
 4     end
 5
 6     def method_missing(method, *args)
 7       check_permissions(method)
 8       @target.send method, args
 9     end
10
11     private 
12     def check_permissions(what)
13       unless can_do?(current_user, what)
14         raise 'Acesso negado!' 
15       end
16     end
17   end
Perguntas?
Obrigado!

More Related Content

What's hot

Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with ReactGreeceJS
 
Ruby closures, how are they possible?
Ruby closures, how are they possible?Ruby closures, how are they possible?
Ruby closures, how are they possible?Carlos Alonso Pérez
 
Oracle naveen Sql
Oracle naveen   SqlOracle naveen   Sql
Oracle naveen Sqlnaveen
 
The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202Mahmoud Samir Fayed
 
Ruby Meetup Balabit
Ruby Meetup BalabitRuby Meetup Balabit
Ruby Meetup BalabitPapp Laszlo
 
The Ring programming language version 1.10 book - Part 103 of 212
The Ring programming language version 1.10 book - Part 103 of 212The Ring programming language version 1.10 book - Part 103 of 212
The Ring programming language version 1.10 book - Part 103 of 212Mahmoud Samir Fayed
 
Java script introducation & basics
Java script introducation & basicsJava script introducation & basics
Java script introducation & basicsH K
 
Jhtp5 20 Datastructures
Jhtp5 20 DatastructuresJhtp5 20 Datastructures
Jhtp5 20 Datastructuresmartha leon
 
[Www.pkbulk.blogspot.com]dbms06
[Www.pkbulk.blogspot.com]dbms06[Www.pkbulk.blogspot.com]dbms06
[Www.pkbulk.blogspot.com]dbms06AnusAhmad
 
MariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeMariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeSergey Petrunya
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2RORLAB
 
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesTo be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesArtur Skowroński
 
New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3Sergey Petrunya
 
Les01-Oracle
Les01-OracleLes01-Oracle
Les01-Oraclesuman1248
 
Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)진성 오
 
The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189Mahmoud Samir Fayed
 
Solr facets and custom indices
Solr facets and custom indicesSolr facets and custom indices
Solr facets and custom indicescgmonroe
 
Building a Hierarchical Data Model Using the Latest IBM Informix Features
Building a Hierarchical Data Model Using the Latest IBM Informix FeaturesBuilding a Hierarchical Data Model Using the Latest IBM Informix Features
Building a Hierarchical Data Model Using the Latest IBM Informix FeaturesAjay Gupte
 

What's hot (20)

Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Ruby closures, how are they possible?
Ruby closures, how are they possible?Ruby closures, how are they possible?
Ruby closures, how are they possible?
 
Oracle naveen Sql
Oracle naveen   SqlOracle naveen   Sql
Oracle naveen Sql
 
The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202The Ring programming language version 1.8 book - Part 32 of 202
The Ring programming language version 1.8 book - Part 32 of 202
 
Oracle
OracleOracle
Oracle
 
Ruby Meetup Balabit
Ruby Meetup BalabitRuby Meetup Balabit
Ruby Meetup Balabit
 
Operator overload rr
Operator overload  rrOperator overload  rr
Operator overload rr
 
The Ring programming language version 1.10 book - Part 103 of 212
The Ring programming language version 1.10 book - Part 103 of 212The Ring programming language version 1.10 book - Part 103 of 212
The Ring programming language version 1.10 book - Part 103 of 212
 
Java script introducation & basics
Java script introducation & basicsJava script introducation & basics
Java script introducation & basics
 
Jhtp5 20 Datastructures
Jhtp5 20 DatastructuresJhtp5 20 Datastructures
Jhtp5 20 Datastructures
 
[Www.pkbulk.blogspot.com]dbms06
[Www.pkbulk.blogspot.com]dbms06[Www.pkbulk.blogspot.com]dbms06
[Www.pkbulk.blogspot.com]dbms06
 
MariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeMariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit hole
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2
 
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesTo be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
 
New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3
 
Les01-Oracle
Les01-OracleLes01-Oracle
Les01-Oracle
 
Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)
 
The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189The Ring programming language version 1.6 book - Part 29 of 189
The Ring programming language version 1.6 book - Part 29 of 189
 
Solr facets and custom indices
Solr facets and custom indicesSolr facets and custom indices
Solr facets and custom indices
 
Building a Hierarchical Data Model Using the Latest IBM Informix Features
Building a Hierarchical Data Model Using the Latest IBM Informix FeaturesBuilding a Hierarchical Data Model Using the Latest IBM Informix Features
Building a Hierarchical Data Model Using the Latest IBM Informix Features
 

Viewers also liked

Design Patterns on Rails
Design Patterns on RailsDesign Patterns on Rails
Design Patterns on Railstchandy
 
Go for Rubyists
Go for RubyistsGo for Rubyists
Go for Rubyiststchandy
 
Abertura do ruby_rails_no_mundo_real_guru_sp
Abertura do ruby_rails_no_mundo_real_guru_spAbertura do ruby_rails_no_mundo_real_guru_sp
Abertura do ruby_rails_no_mundo_real_guru_spWillian Molinari
 
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...David Paniz
 
Aplicacoes para celular com Ruby
Aplicacoes para celular com RubyAplicacoes para celular com Ruby
Aplicacoes para celular com Rubymfcastellani
 
batch - escalando um sistema sem fermento
batch - escalando um sistema sem fermentobatch - escalando um sistema sem fermento
batch - escalando um sistema sem fermentoDouglas Campos
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3Hugo Baraúna
 
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지tok opop
 
Calendrier des activités de JEADER _ AFRIQUE _ 2016
Calendrier des activités de JEADER  _ AFRIQUE _ 2016 Calendrier des activités de JEADER  _ AFRIQUE _ 2016
Calendrier des activités de JEADER _ AFRIQUE _ 2016 JEADER
 
Product Cost Analytics solution overview
Product Cost Analytics solution overviewProduct Cost Analytics solution overview
Product Cost Analytics solution overviewSridhar Pai
 
East Coast Transport-MACRO POINT CASE STUDY
East Coast Transport-MACRO POINT CASE STUDYEast Coast Transport-MACRO POINT CASE STUDY
East Coast Transport-MACRO POINT CASE STUDYPaul Berman
 
Los 12 mandamientos del periodista
Los 12 mandamientos del periodistaLos 12 mandamientos del periodista
Los 12 mandamientos del periodistaIgnacioRamosMancheno
 
Women in Islam & Refutation of some Common Misconceptions
Women in Islam & Refutation of some Common MisconceptionsWomen in Islam & Refutation of some Common Misconceptions
Women in Islam & Refutation of some Common MisconceptionsIslamic Invitation
 
employee-awareness-and-training-the-holy-grail-of-cybersecurity
employee-awareness-and-training-the-holy-grail-of-cybersecurityemployee-awareness-and-training-the-holy-grail-of-cybersecurity
employee-awareness-and-training-the-holy-grail-of-cybersecurityPaul Ferrillo
 
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...Cra-es Conselho
 

Viewers also liked (19)

Design Patterns on Rails
Design Patterns on RailsDesign Patterns on Rails
Design Patterns on Rails
 
Go for Rubyists
Go for RubyistsGo for Rubyists
Go for Rubyists
 
Abertura do ruby_rails_no_mundo_real_guru_sp
Abertura do ruby_rails_no_mundo_real_guru_spAbertura do ruby_rails_no_mundo_real_guru_sp
Abertura do ruby_rails_no_mundo_real_guru_sp
 
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...
Ruby + Rails no Mundo Real 2010 - Voodoo é pra Jacu - Entendendo metaprograma...
 
Aplicacoes para celular com Ruby
Aplicacoes para celular com RubyAplicacoes para celular com Ruby
Aplicacoes para celular com Ruby
 
batch - escalando um sistema sem fermento
batch - escalando um sistema sem fermentobatch - escalando um sistema sem fermento
batch - escalando um sistema sem fermento
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3
 
BDD & Cucumber
BDD & CucumberBDD & Cucumber
BDD & Cucumber
 
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지
창원오피톡 창원오피방 창원오피 오피톡[ optok4] 창원op 창원건마 창원건전마사지
 
Calendrier des activités de JEADER _ AFRIQUE _ 2016
Calendrier des activités de JEADER  _ AFRIQUE _ 2016 Calendrier des activités de JEADER  _ AFRIQUE _ 2016
Calendrier des activités de JEADER _ AFRIQUE _ 2016
 
Product Cost Analytics solution overview
Product Cost Analytics solution overviewProduct Cost Analytics solution overview
Product Cost Analytics solution overview
 
Portadas nacionales 22 marzo-17
Portadas nacionales 22 marzo-17Portadas nacionales 22 marzo-17
Portadas nacionales 22 marzo-17
 
East Coast Transport-MACRO POINT CASE STUDY
East Coast Transport-MACRO POINT CASE STUDYEast Coast Transport-MACRO POINT CASE STUDY
East Coast Transport-MACRO POINT CASE STUDY
 
Los 12 mandamientos del periodista
Los 12 mandamientos del periodistaLos 12 mandamientos del periodista
Los 12 mandamientos del periodista
 
Women in Islam & Refutation of some Common Misconceptions
Women in Islam & Refutation of some Common MisconceptionsWomen in Islam & Refutation of some Common Misconceptions
Women in Islam & Refutation of some Common Misconceptions
 
Sri Lankan Tours
Sri Lankan  ToursSri Lankan  Tours
Sri Lankan Tours
 
employee-awareness-and-training-the-holy-grail-of-cybersecurity
employee-awareness-and-training-the-holy-grail-of-cybersecurityemployee-awareness-and-training-the-holy-grail-of-cybersecurity
employee-awareness-and-training-the-holy-grail-of-cybersecurity
 
Mrs 2017 Orientation
Mrs 2017 OrientationMrs 2017 Orientation
Mrs 2017 Orientation
 
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...
A Administração e a Contabilidade : Uma relação que gera vantagem competitiva...
 

Similar to Refatoração + Design Patterns em Ruby

Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleAnton Shemerey
 
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 RubyVysakh Sreenivasan
 
Thoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguageThoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguagePatricia Aas
 
Identify Literate Code
Identify Literate CodeIdentify Literate Code
Identify Literate Codenatedavisolds
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick touraztack
 
Rooted 2010 ppp
Rooted 2010 pppRooted 2010 ppp
Rooted 2010 pppnoc_313
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadDavid Gómez García
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1Jano Suchal
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Rubyerockendude
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Rubyerockendude
 
Programming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptProgramming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptJoe Kutner
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererRuby Meditation
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015qmmr
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record.toster
 
Impacta - Show Day de Rails
Impacta - Show Day de RailsImpacta - Show Day de Rails
Impacta - Show Day de RailsFabio Akita
 

Similar to Refatoração + Design Patterns em Ruby (20)

Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
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
 
Thoughts On Learning A New Programming Language
Thoughts On Learning A New Programming LanguageThoughts On Learning A New Programming Language
Thoughts On Learning A New Programming Language
 
Identify Literate Code
Identify Literate CodeIdentify Literate Code
Identify Literate Code
 
Migrating legacy data
Migrating legacy dataMigrating legacy data
Migrating legacy data
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
 
Rooted 2010 ppp
Rooted 2010 pppRooted 2010 ppp
Rooted 2010 ppp
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidad
 
RSpec
RSpecRSpec
RSpec
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
Programming JVM Bytecode with Jitescript
Programming JVM Bytecode with JitescriptProgramming JVM Bytecode with Jitescript
Programming JVM Bytecode with Jitescript
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9
 
Steady with ruby
Steady with rubySteady with ruby
Steady with ruby
 
Impacta - Show Day de Rails
Impacta - Show Day de RailsImpacta - Show Day de Rails
Impacta - Show Day de Rails
 

Recently uploaded

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
"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
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
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
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
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
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
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
 

Recently uploaded (20)

Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
"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
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
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
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
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
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
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
 

Refatoração + Design Patterns em Ruby

  • 1. Refatorando Ruby Técnicas de Orientação a Objetos e Design Patterns Aplicados a Linguagens Dinâmicas Cássio Marques Ruby e Rails no Mundo Real 2010
  • 2. cassiomarques.wordpress.com @cassiomarques cassiommc@gmail.com
  • 5. Muitos programadores usando Ruby não sabem usar OO
  • 7. Linguagem nova, mas hábitos antigos
  • 11. Facilitar compreensão do código para novos desenvolvedores
  • 14. Ajudar o Ruby a ser “Enterprise”
  • 16. YAGNI
  • 18.  1 class Bhaskara  2   def solve(a, b, c)  3     # Calcula o delta  4     d = b ** 2 - 4 * a * c  5  6     if d < 0  7       puts 'Raízes complexas - Não sei resolver!'  8     else  9       # calculando raízes 10       r1 = (-b + Math.sqrt(d))/(2.0 * a) 11       r2 = (-b - Math.sqrt(d))/(2.0 * a) 12 13       # imprimindo resultados 14       puts "Raiz 1: #{r1}" 15       puts "Raiz 2: #{r2}" 16     end 17   end 18 end
  • 20. 1 class Bhaskara 2   def initialize(a, b, c) 3     @a, @b, @c = a, b, c 4   end 5 end
  • 21.  1 class Bhaskara  2   def initialize(a, b, c)  3     @a, @b, @c = a, b, c  4   end  5  6   private  7   def delta  8     @b ** 2 - 4 * @a * @c      9   end 10 11   def solve 12     @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a) 13     @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a) 14   end 15 end
  • 22.  1 class Bhaskara  2   def initialize(a, b, c)  3     @a, @b, @c = a, b, c  4   end  5  6   def print_results  7     if delta < 0  8       puts 'Raízes complexas - Não sei resolver!'  9     else 10       solve 11       puts "Raiz 1: #{@r1}" 12       puts "Raiz 2: #{@r2}" 13     end 14   end 15 16   private 17   def delta 18     @b ** 2 - 4 * @a * @c     19   end 20 21   def solve 22     @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a) 23     @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a) 24   end 25 end
  • 23.  1 class Bhaskara  2   def initialize(a, b, c)  3     @a, @b, @c = a, b, c  4   end  5  6   def print_results  7     delta < 0 ? print_complex_results : print_real_results  8   end  9 10   private 11   def delta 12     @b ** 2 - 4 * @a * @c     13   end 14 15   def solve 16     @r1 = (-@b + Math.sqrt(delta))/(2.0 * @a) 17     @r2 = (-@b - Math.sqrt(delta))/(2.0 * @a) 18   end 19 20   def print_real_results 21     solve 22     puts "Raiz 1: #{@r1}" 23     puts "Raiz 2: #{@r2}" 24   end 25 26   def print_complex_results 27     puts 'Raízes complexas - Não sei resolver!' 28   end 29 end
  • 24. O que eu preciso para refatorar?
  • 26. Mantenha seus métodos pequenos http://www.flickr.com/photos/davidden/
  • 27.  1 class ShoppingCart  2   def total_value  3     total = 0  4     for item in @items  5       sub_total = item.value * item.quantity  6       if item.quantity > 3  7         sub_total *= 0.90  8       elsif item.quantity > 6  9         sub_total *= 0.85 10       elsif item.quantiy > 9 11         sub_total *= 0.80 12       end 13       total += sub_total 14     end 15     total 16   end 17 end
  • 28.  1 # - Elimina variáveis temporárias em favor de métodos  2 class ShoppingCart  3   def total_value  4     total = 0  5     for item in @items  6       total += if item.quantity > 3  7         sub_total(item) * 0.90  8       elsif item.quantity > 6  9         sub_total(item) * 0.85 10       elsif item.quantiy > 9 11         sub_total(item) * 0.80 12       end 14     end 15     total 16   end 17 18   def sub_total(item) 19     item.value * item.quantity 20   end 21 end 22
  • 29.  1 # - Método usa apenas atributos de outro objeto  2 #  => Mover!  3 class ShoppingCart  4   def total_value  5     total = 0  6     for item in @items  7       total += if item.quantity > 3  8         item.total_value * 0.90  9       elsif item.quantity > 6 10         item_total_value * 0.85 11       elsif item.quantiy > 9 12         item.total_value = 0.80 13       end        14     end 15     total 16   end 17 end 18 19 class Item 20   def total_value 21     @value * @quantity 22   end 23 end
  • 30.  1 # - Método fazendo coisa demais  2 # => Extrair!  3 class ShoppingCart  4   def total_value  5     total = 0  6     for item in @items  7       total += item.total_value * discount(item.quantity)  8     end  9     total 10   end 11 12   def discount(quantity) 13     case quantity 14     when (1..2); 1.00 15     when (3..5); 0.90 16     when (6..8); 0.85 17     else 0.80     18     end 19   end 20 end
  • 31.  1 # - Use Ruby!  2 class ShoppingCart  3   def total_value  4     items.inject(0.0) { |sum, item|   5       sum += item.total_value * discount(item.quantity)  6     }  7   end  8  9   def discount(quantity) 10     case quantity 11     when (1..2); 1.00 12     when (3..5); 0.90 13     when (6..8); 0.85 14     else 0.80     15     end 16   end 17 end
  • 32. Faça objetos se comportarem como coleções http://www.flickr.com/photos/deepsignal/366774303/sizes/l/
  • 33.  1 class Library  2   def search_book_by_title(title)  3     @books.select { |book| book.title == title }  4   end  5  6   def search_book_by_author(author)  7     @books.select { |book| book.author == author }  8   end  9 10   def sort_by_title 11     @books.sort_by { |book| book.title } 12   end 13 14   def authors 15     @books.map { |book| book.author } 16   end 17 18   # ... 19 end
  • 34.  1 class Library  2   include Enumerable  3  4   def each  5     @books.each { |book| yield book }  6   end  7 end  8  9 library.each { |book| ... } 10 library.inject { |book| ... } 11 library.map { |book| ... } 12 library.sort { |book| ... } 13 # ...
  • 35. Dê nomes aos parâmetros dos métodos http://www.flickr.com/photos/giantginkgo/
  • 36.  1 class Dialog  2   def initialize(height, width, name, title)  3     @height = height  4     @width  = width  5     @name   = name  6     @title  = title  7   end  8 end  9 10 dialog = Dialog.new 200, 400, 'dialog1', 'A Dialog'
  • 37.  1 class Dialog  2   def initialize(options)  3     @height = options[:height]  4     @width  = options[:width]  5     @name   = options[:name]  6     @title  = options[:title]  7   end  8 end  9 10 dialog = Dialog.new( 11   :height => 200, 12   :width  => 400, 13   :name   => 'dialog1', 14   :title  => 'A Dialog' 15 )
  • 39.  1 class Person  2   def state=(state)  3     unless [:sick, :healthy].include?(state)  4       raise ArgumentError, "unknown state: #{state}"   5     end  6     @state = state  7   end  8 end  9 10 class Vehicle 11   def state=(state) 12     unless [:parked, :running].include?(state) 13       raise ArgumentError, "unknown state: #{state}"  14     end 15     @state = state 16   end 17 end
  • 40.  1 module HasStates  2   def has_states(*args)  3     define_method :state= do |new_state|  4       unless args.include?(new_state)  5         raise ArgumentError, "unknown state: #{state}"   6       end  7       @state = new_state  8     end  9   end 10 end
  • 41.  1 class Person  2   extend HasStates  3  4   has_states :sick, :healthy  5 end  6  7 class Vehicle  8   extend HasStates  9 10   has_states :parked, :running 11 end 12 13 Object.extend HasStates
  • 42. Uma classe não deve realizar trabalhos que não lhe pertencem...
  • 43. 1 class Person 2   attr_accessor :telephone_number, :telephone_area_code 3 4   def formatted_telephone 5     "(#{telephone_area_code}) #{telephone_number}" 6   end 7 end
  • 44.  1 class Person  2   def initialize  3     @telephone_number = TelephoneNumber.new  4   end  5 end  6  7 class TelephoneNumber  8   attr_accessor :area_code, :number  9 10   def formatted 11     "(#{area_code}) #{number}" 12   end 13 end
  • 46.  1 class Queue  2   def initialize  3     @queue = []  4   end  5  6   def enqueue(element)  7     @queue.unshift element      8   end  9 10   def dequeue 11     @queue.pop 12   end 13 end
  • 47. O Ruby pode dar uma ajudinha...
  • 48.  1 require 'forwardable'  2  3 class Queue  4   extend Forwardable  5  6   def initialize  7     @queue = []  8   end  9 10   def_delegator :@queue, :unshift, :enqueue 11   def_delegator :@queue, :pop, :dequeue 12 end
  • 49. Não exponha o interior de seus objetos sem necessidade http://www.flickr.com/photos/mwichary/
  • 50.  1 class Room  2   attr_reader :air_conditioner  3 end  4  5 class AirConditioner  6   attr_reader :sensor  7 end  8  9 class TemperatureSensor 10   def temperature 11     #... 12   end 13 end 14 15 if room.air_conditioner.sensor.temperature > 28 16   room.air_conditioner.on 17 end
  • 51.  1 class Room  2   attr_reader :air_conditioner  3  4   def temperature  5     air_conditioner.sensor.temperature  6   end  7 end  8  9 if room.temperature > 28 10   room.air_conditioner.on 11 end
  • 52. Substitua números mágicos por constantes http://decluttr.com/4524127771_white
  • 53. 1 class Circle 2   def area 3     3.14159265 * (r ** 2) 4   end 5 end
  • 54. 1 class Circle 2   PI = 3.14159265  3 4   def area 5     PI * (r ** 2) 6   end 7 end
  • 55. Encapsule coleções de objetos http://www.flickr.com/photos/eagleglide/
  • 56.  1 class Cart  2   attr_accessor :products  3 end  4  5 class Product  6   attr_reader :value, :name  7  8   def initialize(name, value)  9     @name, @value = name, value 10   end 11 end
  • 57. 1 products = [] 2 products << Product.new('Camiseta', 35.00) 3 products << Product.new('Bermuda', 38.00) 4 products << Product.new('Boné', 20.00) 5 cart = Cart.new 6 cart.products = products 7 cart.products.pop # => alterei o estado do carrinho
  • 58.  1 class Cart  2   def initialize  3     @products = []  4   end  5  6   def add_product(product)  7     @products << product      8   end  9 10   def remove_product(product) 11     @products.delete product 12   end 13 end 14 15 cart = Cart.new 16 cart.add_product(Product.new('Camiseta', 35.00))
  • 59. Substitua condicionais por polimorfismo http://www.flickr.com/photos/randyread/
  • 60.  1 class Tax  2   def initialize(type, value)  3     @type = type      4     @value = value  5   end  6  7   def retained_value  8     case @type  9     when :irpj;   @value * 0.015 10     when :pis;    @value * 0.0065 11     when :cofins; @value * 0.030 12     when :iss;    0.0 13     end 14   end 15 16   def due_value 17     case @type 18     when :irpj;   @value * 0.033 19     when :pis;    0.0 20     when :cofins; 0.0 21     when :iss;    @value * 0.02 22     end 23   end 24 end
  • 61.  1 module Tax  2   def due_value  3     @due_rate * @value      4   end  5  6   def retained_value  7     @retained_rate * @value  8   end  9 end 10 11 class IrpjTax 12   include Tax 13 14   def initialize(value) 15     @value         = value 16     @due_rate      = 0.033 17     @retained_rate = 0.015 18   end 19 end 20 21 # o mesmo para as demais classes...
  • 62.  1 class Invoice  2   def initialize(value)  3     @value = value  4     create_taxes  5   end  6  7   def add_tax(tax)  8     @taxes << tax  9   end 10    11   def total_taxes_value 12     @taxes.inject(0.0) { |sum, tax| 13       sum += tax.due_value + tax.retained_value 14     } 15   end 16 17   private 18   def create_taxes 19     @taxes = [] 20     @taxes << IrpjTax.new(@value) 21     @taxes << PisTax.new(@value) 22     @taxes << CofinsTax.new(@value) 23     @taxes << IssTax.new(@value) 24   end 25 end 26 27 invoice = Invoice.new 1400.00 28 puts invoice.total_taxes_value
  • 63. Simplifique expressões condicionais
  • 64. 1 if product.release_date < 3.months.ago || quantity > 100 2   self.value *= 0.90 3 end
  • 65.  1 if elegible_for_discount?  2   self.value *= 0.90  3 end  4  5 def elegible_for_discount?  6   old? && great_quantity?  7 end  8  9 def old? 10   product.release_date < 3.months.ago 11 end 12 13 def great_quantity? 14   quantity > 100 15 end
  • 66. http://www.flickr.com/photos/jeff_oliver/ Mas uma expressão condicional pode ser melhor que ifs aninhados...
  • 67. 1 if age > 40 2   if gender == :male 3     if last_visit > 1.month.ago 4       # ... 5     end 6   end 7 end
  • 68. 1 if age > 40 && gender == :male && last_visit > 1.month 2   # ... 3 end 4 5 # e a partir daqui podemos extrair as condições para 6 # métodos...
  • 69. Às vezes faz mais sentido juntar do que separar...
  • 70. 1 class Bicycle 2   def press_front_brake 3     brakes[:front].press 4   end 5 6   def press_rear_brake 7     brakes[:rear].press 8   end 9 end
  • 71. 1 class Bicycle 2   def press_brake(brake) 3     brakes[brake].press 4   end 5 end
  • 72. Verifique se a mensagem pode ser enviada http://www.flickr.com/photos/funtik/
  • 73. 1 def do_something(target) 2   target.prepare rescue nil 3   target.explode 4 end
  • 74. 1 def do_something(target) 2   target.prepare if target.respond_to? :prepare 3   target.explode 4 end
  • 76.  1 class CdPlayer  1 class TapeDeck  2   def turn_on  2   def turn_on  3     @on = true  3     @on = true  4   end  4   end  5  5  6   def turn_off  6   def turn_off  7     @on = false  7     @on = false  8   end  8   end  9  9 10   def play 10   def play 11     play_disc 11     play_tape 12   end 12   end 13 end 13 end
  • 77.  1 class AudioDevice  2   def turn_on  3     @on = true  4   end  5  6   def turn_off  7     @on = false  8   end  9 end 10 11 class CdPlayer < AudioDevice 12   def play 13     play_disk 14   end 15 end 16 17 class TapeDeck < AudioDevice 18   def play 19     play_tape 20   end 21 end
  • 79.  1 class Text  2   attr_reader :contents  3  4   def left_aligned_format  5     # ...  6   end  7  8   def right_aligned_format  9     # ... 10   end 11 12   def justified_format 13     # ... 14   end 15 end
  • 80.  1 class LeftAlignedFormatter  2   def format(context)  3     align_left context.contents  4   end  5 end  6  7 class RightAlignedFormatter  8   def format(context)  9     align_right context.contents 10   end 11 end 12 13 class RightJustifiedFormatter  14   def format(context) 15     justify context.contents 16   end 17 end
  • 81.  1 class Text  2   attr_reader :contents  3   attr_accessor :formatter  4  5   def initialize(contents, formatter)  6     @contents, @formatter = contents, formatter  7   end  8  9   def format 10     @formatter.format self 11   end 12 end
  • 83.  1 class Text  2   attr_reader :contents  3   attr_accessor :formatter  4  5   def initialize(contents, &formatter)  6     @contents, @formatter = contents, formatter  7   end  8  9   def format 10     @formatter.call self 11   end 12 end 13 14 left_aligned_text = Text.new 'some text' do |context| 15   align_left context.contents 16 end
  • 84. Use quando você precisar alterar o algorítmo em tempo de execução
  • 86.  1 class Document  2   def change_text_color(color)  3     @text.color = color  4   end  5  6   def change_background_color(color)  7     @text.background_color = color      8   end  9 10   def change_font_size(size) 11     @text.font_size = size     12   end 13 14   def change_font(font) 15     @text.font = font 16   end 17 end
  • 88.  1 class Command  2   attr_reader :description  3  4   def initialize(description)  5     @description = description      6   end  7 end
  • 89.  1 class ChangeTextColorCommand < Command  2   def initialize(target)  3     super("Altera a cor do texto")      4     @target = target  5   end  6  7   def execute(color)  8     @old_color = @target.text.color  9     @target.text.color = color 10   end   11 12   def unexecute 13     @target.text.color = @old_color if @old_color 14   end 15 end
  • 90.  1 class Document  2   def initialize  3     @commands = []  4   end  5  6   def change_text_color(color)  7     run_command ChangeTextColorCommand.new(self), color  8   end  9 10   def change_font(font) 11     run_command ChangeFontCommand.new(self), font 12   end 13 14   def undo_last_action 15     @commands.pop.unexecute unless @commands.empty? 16   end 17 18   private 19   def run_command(command, param) 20     command.execute param 21     @commands << command 22   end 23 end
  • 91. Use quando você precisar realizar tarefas específicas e mantê-las em um registro
  • 92. Proxy
  • 93.  1 class Task   2   def initialize(creator)  3     @creator = creator  4   end  5  6   def owner=(owner)  7     @owner = owner      8   end  9 10   def add_comment(comment) 11     @comments << comment 12   end 13 14   def update_description(new_description) 15     @description = description 16   end 17 18   def close 19     @status = :closed 20   end 21 end
  • 94.  1 class TaskProtectionProxy  2   def initialize(target)  3     @target = target      4   end  5  6   def owner=(owner)  7     check_permissions :owner=  8     @owner = owner      9   end 10 11   def add_comment(comment)     12     check_permissions :add_comment 13     @comments << comment 14   end 15 16   # ... 17 18   private 19   def check_permissions(what) 20     unless can_do?(current_user, what) 21       raise 'Acesso negado!'  22     end 23   end 24 end
  • 95.  1 class TaskProtectionProxy  2   def initialize(target)  3     @target = target  4   end  5  6   def method_missing(method, *args)  7     check_permissions(method)  8     @target.send method, args  9   end 10 11   private  12   def check_permissions(what) 13 unless can_do?(current_user, what) 14       raise 'Acesso negado!'  15     end 16   end 17 end

Editor's Notes