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'
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
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
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...
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
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