Post on 24-May-2015
description
O que você NÃO aprendeu sobre Orientação a ObjetosDanilo Sato@dtsato
Danilo Sato@dtsato - www.dtsato.com
Desenvolvedor, Arquiteto, Coach, DevOps, Treinador
Como aprendemos OO?
Orientação a Objetos é:Herança +
Polimorfismo +Encapsulamento
Orientação a Objetos é:Modelar o Mundo Real
“A execução de um programa é considerada um modelo físico, simulando o comportamento de
uma parte real ou imaginária do mundo."-- Kristen Nygaard
“Programação orientada a objetos é uma péssima ideia, que só poderia ter nascido na
Califórnia."-- Edsger W. Dijkstra
“Programação orientada a objetos é uma péssima ideia, que só poderia ter nascido na
Califórnia."-- Edsger W. Dijkstra
“Na Ciência da Computação, arrogância é medida em nano-Dijkstras"
-- Alan Kay
Inventou o termo “Orientação a Objetos”
Inventou o termo “Orientação a Objetos”
Smalltalk
Células
Inventou o termo “Orientação a Objetos”
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"
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"
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"
“...(Erlang) é a única linguagem orientada a objetos e talvez eu tenha sido prematuro em
dizer o que era orientação a objetos"
-- Joe Armstrong
Orientação a Objetos:Programa?Linguagem?Paradigma?
Modelo Computacional?
Orientação a Objetos:Programa?Linguagem?Paradigma?
Modelo Computacional?
Ninguém Concorda
Esta palestraé sobre oo
Esta palestraNão é sobre oo
Esta palestraé sobre DESIGNDESIGN
O que é ?DESIGN
DESIGN Código==
DESIGN Código==
Estrutura
Organização
FlexibilidadeTestabilidade
Legibilidade
Coesão
Acoplamento
Dependências
BOM reduz ocusto da mudança
DESIGN
DESIGN
Hipótese da stamina do DESIGN
Func
iona
lidad
es
Tempo
Func
iona
lidad
es
Tempo
Sem Design
Func
iona
lidad
es
Tempo
Bom Design
Sem Design
Func
iona
lidad
es
Tempo
Bom Design
Sem DesignOnde o design
se paga
2004!
Design foi esquecido
Rails
Design foi esquecido
RailsModelView
ControllerHelperMailer
...
Model
View
Controller
ZeroDesign
DesignÁgil
Up-frontDesign
DESIGN É BOM
Design “ativo”
DESIGN É BOM
Design “passivo”
DESIGN É BOM
Design ágil == Design evolutivo
DESIGN É BOM
Design ágil == Design evolutivo
TUDO É UM OBJETO!
TUDO É UM OBJETO?
TUDO É UM OBJETO?
class?
TUDO É UM OBJETO?
if?
class?
TUDO É UM OBJETO?
while?if?
class?
Smalltalk
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.
class TrueClass def if_true(is_true, otherwise: -> {}) is_true.call end
def if_false(is_false, otherwise: -> {}) otherwise.call endend
class FalseClass def if_true(is_true, otherwise: -> {}) otherwise.call end
def if_false(is_false, otherwise: -> {}) is_false.call endend
Condições
2.0.0 > (2 > 1).if_true -> {2.0.0?> puts "sim"2.0.0?> }, otherwise: -> {2.0.0?> puts "não"2.0.0?> }sim => nil
2.0.0 > (1 > 2).if_true -> {2.0.0?> puts "sim"2.0.0?> }, otherwise: -> {2.0.0?> puts "não"2.0.0?> }não => nil
Condições
class Proc def while_true(&blk) self.call.if_true -> { blk.call while_true(&blk) } endend
2.0.0?> i = 02.0.0?> -> {i < 3}.while_true do2.0.0?> puts i2.0.0?> i += 12.0.0?> end012 => nil
Loops
Herança
Herança
“É um”
Ave
Pato Pinguim
+ voa()
+ voa() + voa()
class Bird def fly puts "flap, flap, flap" endend
class Penguin < Bird def fly raise "I don't know how to fly" endend
flock = [Bird.new, Bird.new, Bird.new]flock.each { |bird| bird.fly }# >> flap, flap, flap# >> flap, flap, flap# >> flap, flap, flap
class Bird def fly puts "flap, flap, flap" endend
class Penguin < Bird def fly raise "I don't know how to fly" endend
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'
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
Isto não é uma ave.Isto não é uma ave.
Herança
“É um”
Herança
“É um”
Herança
Herança?
Herança
class Book < ActiveRecord::Base def initialize(attributes = nil, options = {}) super @my_cache = {} end def number_of_pages @my_cache[:number_of_pages] ||= 10000 endend
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)
class Book < ActiveRecord::Base def after_initialize @my_cache = {} end def number_of_pages @my_cache[:number_of_pages] ||= 10000 endend
Book.create( :title => "Lord of the Rings").number_of_pages # => 10000
Book.find_by( :title => "Lord of the Rings").number_of_pages # => 10000
Herança:Preciso entender o que a(s) classe(s)
Pai faz(em)!
class Deck < Array def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) cards = indexes.product(suits) super(cards) end
def draw(n) self.pop(n) endend
deck = Deck.newdeck.shuffle!.draw(5) # => [["6", "H"], ["Q", "H"], ["3", "C"], ["6", "S"], ["K", "C"]]
deck << ["A", "S"] << ["A", "S"]deck.count { |card| card[0] == "A"} # => 6 aces?
Não use herança se não usar todo o comportamento
do(s) pais(s)
Herança é perigoso
Herança é perigoso
Herança é perigoso
Herança é perigoso
Herança é perigoso
Use Herança quando há
especialização
Prefira hierarquias
rasas
BigDecimal RationalComplexFloatInteger
Fixnum Bignum
Numeric
Agregação e composição
Agregação Composição
“Tem um”
Agregação
Agregação
Agregação
composição
composição
composição
class Deck def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) @cards = indexes.product(suits) end
def count(&blk); @cards.count(&blk) end def <<(card) @cards << card unless @cards.include?(card) self endend
deck = Deck.newdeck << ["A", "S"] << ["A", "S"]deck.count { |card| card[0] == "A"} # => 4
Prefira composição ao
invés de Herança
Delegação
Delegação
require 'forwardable'class Deck extend Forwardable def_delegator :@cards, :pop, :draw def_delegators :@cards, :count
def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) @cards = indexes.product(suits) end
def <<(card) @cards << card unless @cards.include?(card) self endend
deck = Deck.newdeck.draw(5) # => [["Q", "D"], ["K", "S"], ["K", "H"], ["K", "C"], ["K", "D"]]
polimorfismo
polimorfismo
polimorfismo
1. Herança
1. Herança2. Duck Typing
1. Herança2. Duck Typing3. Mixins
permite separar abstração da concretização
permite separar “O que” do
“Como”
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
MITO: Modelar OO é modelar o mundo real
Actor
Ghost Pacman
center, direction+ collidesWith(Actor)+ advance(millis)+ getNextDirection()
Actor
GhostStrategy
PacmanStrategy
MovementStrategy+ getNextDirection()
Actor
RandomStrategy
UserControlStrategy
MovementStrategy+ getNextDirection()
Actor
RandomStrategy
UserControlStrategy
MovementStrategy+ getNextDirection()
TargetChasingStrategy
+ getTarget()
o design evolui Conforme o
entendimento do domínio evolui
[ ] 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)[ ] Blues
Filtros
Artista
Album
Estilo
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 endend
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 endend
o domínionão é música
o domínioé busca
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 ... endend
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 endend
Busca
Música
DocumentFilter
Facet
Indexer
SongAlbum
Artist
ContextosDelimitados
Busca
Música
DocumentFilter
Facet
Indexer
SongAlbum
Artist
Mapa de Contextos
Busca
Música
“Todos os modelos estão errados,alguns modelos são úteis"
-- George Box
MITO: Modelar OO é modelar o mundo real
MITO: Modelar OO é modelar o mundo real
Resumindo...
OO é passagemde mensagem
HerançaagregaçãoComposiçãodelegação
polimorfismo
DESIGN É BOM
ZeroDesign
DesignÁgil
Up-frontDesign
Design ágil == Design evolutivo
DESIGN É BOM
ZeroDesign
DesignÁgil
Up-frontDesign
Design ágil == Design evolutivo
Não modele o mundo real
modele oseu domínio
aprenda oseu domínio
evolua oseu domínio
se divirta!
Obrigado!
Danilo Sato@dtsato - www.dtsato.com
Desenvolvedor, Arquiteto, Coach, DevOps, Treinador
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: