Upload
marcos-brizeno
View
2.868
Download
0
Embed Size (px)
DESCRIPTION
Formas de como aplicar metaprogramação com Ruby e principalmente os cuidados para quando se aplicar.
Citation preview
META PROGRAM
AÇÃO RUBY
Marcos Brizeno
Cientista da Computação
Consultor ThoughtWorks
Cearense!
@marcosbrizeno
brizeno.wordpress.com
Avisos
Conteúdo não indicado para menores de 18 anos
Exemplos de código não foram testados
<jabá>
</jabá>
ü Discutir o que é metaprogramação
ü Diferenciar reflexão e
metaprogramação
ü Como a metaprogramação pode
nos ajudar
ü Como a metaprogramação pode
nos atrapalhar
ü Se divertir :D
⊠ Ruby
⊠ Orientação a Objetos
O que é Metaprogramação?
WAT???
§ Código que escreve código
§ Programa que escreve programas
§ Altera código em tempo de execução
§ Alterar o comportamento do programa com o programa
§ Lógica escondidada dentro de si mesma
Reflexão
§ Inspecionar o próprio objeto § respond_to? § methods § class_variable_get/set
Metaprogramação
§ Programa que escreve programa § define_method § method_missing § class_eval
O que é Metaprogramação?
WAT???
Metaprogramação
§ Código genérico
§ Remove duplicações
§ É muito foda =)
Metaprogramação
§ Código difícil de ler
§ Complexo
§ É muito foda =(
Exemplo Simples:
§ Ruby accessors: § attr_accessor § attr_reader § attr_writer
class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end
class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end
Modificadores de
visibiliade/acesso
class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end
Modificadores de
visibiliade/acesso
Attributos da �
classe/instancias
class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end
Modificadores de
visibiliade/acesso
Attributos da �
classe/instancias
class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end
Modificadores de
visibiliade/acesso
Attributos da �
classe/instancias
Rails Models
class Product < ActiveRecord::Base end
Rails Models
class Product < ActiveRecord::Base end
Cadê os atributos?
Cadê o construtor?
Métodos que definem métodos
§ Definidos na class Module
Exemplo: attr_accessor
@attr = nil def attr() @attr end def attr=(attr) @attr = attr end
Exemplo: attr_accessor
@attr = nil def attr() @attr end def attr=(attr) @attr = attr end
Método para �
ler o valor
Método para �
escrever um�
valor
Como o ruby sabe qual o nome da minha variável?
Vamos pensar um pouco…
#define_method
symbol é o nome�do método que vai �ser criado
block é o que esse �novo método vai fazer
#define_method
def create_method(name, &block)
self.class.send(:define_method, name, block)
end Podemos criar qualquer método �em qualquer lugar em qualquer �momento!
Ruby tem classes “abertas”
§ Podemos adicionar ou sobrescrever métodos em uma classe em qualquer momento
§ Podemos adicionar ou sobrescrever métodos em uma instância em qualquer momento
Classes ou Instâncias???
Nota sobre mapa do objeto
Classes são Objetos
§ CONSTANTES são escritas com letras maiúsculas
§ Uma classe é só uma Constante apontando para um objeto do tipo Class
Exemplo real #showmethecode
Um exemplo mais “interessante”
Um sistema de vendas de revistas
Eventos: • Nova venda • Nova promoção • Revista em falta
Interessados: • Clientes (email) • Gerentes (ActiveMQ) • Outros apps (WS)
Fontes: • Controllers • Workers • Models
Resolvendo com programação
Controller
Model
Worker
Notifier -sell() notify_client notify_manager notify_app1 -out_of_stock()
EmailHandler
ActiveMQHandler
RestHandler
Resolvendo com programação
Controller
Model
Worker
Notifier -sell() notify_client notify_manager notify_app1 -out_of_stock()
EmailHandler
ActiveMQHandler
RestHandler
Notifier tem muitas responsabilidades
Notifier quebra �muito fácil
Notifier está sobrecarregado
Resolvendo com programação
Controller
Model
Worker
Notifier -sell() ClientNotifier.notify_sell() ManagerNotifier.notify_sell() App1Notifier.notify_sell() -out_of_stock()
EmailHandler
ActiveMQHandler
RestHandler
ClientNotifier
ManagerNotifier
App1Notifier
Resolvendo com programação
Controller
Model
Worker
Notifier -sell() ClientNotifier.notify_sell() ManagerNotifier.notify_sell() App1Notifier.notify_sell() -out_of_stock()
EmailHandler
ActiveMQHandler
RestHandler
ClientNotifier
ManagerNotifier
App1Notifier
Classes especializadas
Ainda existe código �duplicado
Melhorando com metaprogramação
Controller
Model
Worker
Notifier EVENTOS = [:sell, …] NOTIFIERS = [ClientNotifier, …]
EmailHandler
ActiveMQHandler
RestHandler
ClientNotifier
ManagerNotifier
App1Notifier
Podemos varrer a lista de notifiers e eventos para chamar as devidas notificações
Melhorando com metaprogramação
Analisando a solução
§ Define vários métodos em tempo de execução
§ Código genérico
§ Remove duplicações
§ É muito foda =)
Analisando a solução
§ O método nunca ser utilizado
§ Código difícil de ler
§ Complexo
§ É muito foda =(
#method_missing
se o ruby não sabe o que fazer ele chama �o method_missing
Outra solução com metaprogramação
#method_missing
§ Executado quando um método não é encontrado
§ Última tentativa antes de lançar NoMethodError
§ Só é executado após percorrer todo o mapa do objeto
Ruby method lookup
Procura no �
objeto
Ruby method lookup
Procura no �
objeto Procura na �
classe
Ruby method lookup
Procura no �
objeto Procura na �
classe
Procura nas �
superclasses
Ruby method lookup
Procura no �
objeto Procura na �
classe
Procura nas �
superclasses
Procura nos �módulos
Ruby method lookup
Procura no �
objeto Procura na �
classe
Procura nas �
superclasses
Procura nos �módulos
Procura na �
classe da �
classe
Analisando a solução
§ Só executa quando o método é chamado
§ Código genérico
§ Remove duplicações
§ É muito foda =)
Analisando a solução
§ Percorre todo o mapa de objetos
§ Código difícil de ler
§ Complexo
§ É muito foda =(
Outra solução com metaprogramação
Analisando a solução
§ Só executa quando o método é chamado
§ Cria o método pra evitar outra busca
§ Código genérico
§ Remove duplicações
§ É muito foda =)
Analisando a solução
§ Código difícil de ler
§ Complexo
§ É muito foda =(
Outra possível solução
§ class_eval / instance_eval
§ String -> Código
“def #{event}” +
“ #chama notifiers” +
“end”
§ PERIGO!!!
Aprecie com moderação
§ Lógica de negócio NÃO DEVE ser metaprogramada
§ Muita mágica aumenta o tempo de aprendizado de novos devs
§ Debugar o código fica difícil
§ Modificações em uma única parte são difíceis
Quais os próximos passos
§ Entender Modelo de Objetos do Ruby
§ Singleton class/Eigenclass
§ Lambdas e Procs
§ Soluções alternativas para metaprogramação
OBRIGADO! @marcosbrizeno
Geek Night Recife