Este documento discute os conceitos e mitos em torno da Orientação a Objetos. Ele explica que OO é sobre passagem de mensagens e não modelagem do mundo real. Design é importante e deve evoluir conforme o entendimento do domínio. Herança deve ser usada com cuidado e composição é preferível.
17. Inventou o termo “Orientação a
Objetos”
“OO significa passagem de mensagem,
retenção local, proteção e ocultação do estado
de um processo, e associação tardia de tudo"
18. Inventou o termo “Orientação a
Objetos”
“OO significa passagem de mensagem,
retenção local, proteção e ocultação do estado
de um processo, e associação tardia de tudo"
“A grande ideia é passagem de mensagem"
19. Inventou o termo “Orientação a
Objetos”
“OO significa passagem de mensagem,
retenção local, proteção e ocultação do estado
de um processo, e associação tardia de tudo"
“A grande ideia é passagem de mensagem"
“OO é um modelo computacional, não um
paradigma de programação"
20.
21.
22. “...(Erlang) é a única linguagem orientada a
objetos e talvez eu tenha sido prematuro em
dizer o que era orientação a objetos"
-- Joe Armstrong
60. WARNING!
O código que você está prestes a ler foi escrito
com o propósito educacional. Não faça isso em
casa ou coloque código parecido em produção.
61. class TrueClass
def if_true(is_true, otherwise: -> {})
is_true.call
end
def if_false(is_false, otherwise: -> {})
otherwise.call
end
end
class FalseClass
def if_true(is_true, otherwise: -> {})
otherwise.call
end
def if_false(is_false, otherwise: -> {})
is_false.call
end
end
Condições
63. class Proc
def while_true(&blk)
self.call.if_true -> {
blk.call
while_true(&blk)
}
end
end
2.0.0?> i = 0
2.0.0?> -> {i < 3}.while_true do
2.0.0?> puts i
2.0.0?> i += 1
2.0.0?> end
0
1
2
=> nil
Loops
67. class Bird
def fly
puts "flap, flap, flap"
end
end
class Penguin < Bird
def fly
raise "I don't know how to fly"
end
end
flock = [Bird.new, Bird.new, Bird.new]
flock.each { |bird| bird.fly }
# >> flap, flap, flap
# >> flap, flap, flap
# >> flap, flap, flap
68. class Bird
def fly
puts "flap, flap, flap"
end
end
class Penguin < Bird
def fly
raise "I don't know how to fly"
end
end
flock = [Penguin.new, Penguin.new,
Penguin.new]
flock.each { |bird| bird.fly }
# ~> -:9:in `fly': I don't know how to fly
(RuntimeError)
# ~> from -:14:in `block in <main>'
# ~> from -:14:in `each'
69. Princípio de Substituição
de Liskov
Se S é um subtipo de T, então os
objetos do tipo T podem ser
substituídos pelos objetos de tipo
S em qualquer lugar do programa
77. class Book < ActiveRecord::Base
def initialize(attributes = nil, options = {})
super
@my_cache = {}
end
def number_of_pages
@my_cache[:number_of_pages] ||= 10000
end
end
Book.create(
:title => "Lord of the Rings").number_of_pages
# => 10000
Book.find_by(
:title => "Lord of the Rings").number_of_pages
# ~> -:8:in `number_of_pages': undefined method
`[]' for nil:NilClass (NoMethodError)
78. class Book < ActiveRecord::Base
def after_initialize
@my_cache = {}
end
def number_of_pages
@my_cache[:number_of_pages] ||= 10000
end
end
Book.create(
:title => "Lord of the Rings").number_of_pages
# => 10000
Book.find_by(
:title => "Lord of the Rings").number_of_pages
# => 10000
112. Princípio “Open-Closed”
Entidades de software como
classes, módulos e funções devem
ser abertas para extensão, mas
fechadas para modificação
-- Bertrand Meyer
120. [ ] Metallica (10)
[ ] Iron Maiden (5)
[ ] AC/DC (15)
[ ] ...
[ ] Black Album (5)
[ ] Master of
Puppets (5)
[ ] Killers (5)
[ ] ...
[x] Rock (50)
[ ] Clássico (100)
[ ] Jazz (80)
Filtros
Artista
Album
Estilo
121. class Song < ActiveRecord::Base
searchable do
string :title
string :album { album.title }
string :artist { album.artist.name }
...
end
def self.build_with_filters(p={})
search = Sunspot.new_search(Song)
search.build do
title = with(:title, p[:title]) if p[:title].present?
artist = with(:artist, p[:artist]) if p[:artist].present?
album = with(:album, p[:album]) if p[:album].present?
...
facet :artist, exclude: artist
facet :album, exclude: album
end
search
end
end
122. class Song < ActiveRecord::Base
...
def self.build_with_filters(p={})
search = Sunspot.new_search(Song)
if p[:artist]
to_reject = p[:artist_album].map do |artist_album|
JSON.parse(artist_album)['album']
end
p[:album].reject! do |element|
to_reject.include?(element)
end
p[:album] = [{}] if p[:album].empty?
end
search.build do
...
end
search
end
end
125. require 'forwadable'
module Search
class SongDocument
extend Forwardable
def_delegators :@song, :title
def initialize(song)
@song = song
end
def album
@song.album.title
end
def artist
@song.artist.name
end
...
end
end
126. module Search
class SongDocument
def self.search_filters(p={})
[
Search::OptionalFilter.new(:artist, p),
Search::AlbumFilter.new(:artist, :artist_album, p),
Search::OptionalFilter.new(:title, p)
]
end
def self.build_with_filters(filters, p={})
Sunspot.new_search(Song).tap do |search|
filters.each do |filter|
filter.apply_to(search)
end
Search::Faceter.new(filters, p).apply_to(search)
end
end
end
end
147. Referências
• “Practical Object-Oriented Design in Ruby” Sandi Metz
• “Domain-Driven Design: Tackling Complexity in the Heart of
Software” Eric Evans
• “Analysis Patterns: Reusable Object Models” Martin Fowler
• “Patterns of Enterprise Application Architecture” Martin Fowler
• “Design Patterns: Elements of Reusable Object-Oriented
Software” Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
• “Growing Object-Oriented Software, Guided by Tests” Steve
Freeman , Nat Pryce
• “Object-Oriented Software Construction” Bertrand Meyer
Livros: