Metaprogramação Ruby

67
META PROGRAM AÇÃO RUBY Marcos Brizeno

description

Formas de como aplicar metaprogramação com Ruby e principalmente os cuidados para quando se aplicar.

Transcript of Metaprogramação Ruby

Page 1: Metaprogramação Ruby

META PROGRAM

AÇÃO RUBY

Marcos Brizeno

Page 2: Metaprogramação Ruby

Cientista da Computação

Consultor ThoughtWorks

Cearense!

@marcosbrizeno

brizeno.wordpress.com

Page 3: Metaprogramação Ruby

Avisos

Page 4: Metaprogramação Ruby

Conteúdo não indicado para menores de 18 anos

Page 5: Metaprogramação Ruby

Exemplos de código não foram testados

Page 6: Metaprogramação Ruby
Page 7: Metaprogramação Ruby

<jabá>

</jabá>

Page 8: Metaprogramação Ruby

ü 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

Page 9: Metaprogramação Ruby

⊠ Ruby

⊠ Orientação a Objetos

Page 10: Metaprogramação Ruby

O que é Metaprogramação?

WAT???

Page 11: Metaprogramação Ruby

§ 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

Page 12: Metaprogramação Ruby
Page 13: Metaprogramação Ruby

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

Page 14: Metaprogramação Ruby

O que é Metaprogramação?

WAT???

Page 15: Metaprogramação Ruby

Metaprogramação

§ Código genérico

§ Remove duplicações

§ É muito foda =)

Page 16: Metaprogramação Ruby

Metaprogramação

§ Código difícil de ler

§ Complexo

§ É muito foda =(

Page 17: Metaprogramação Ruby

Exemplo Simples:

§ Ruby accessors: § attr_accessor § attr_reader § attr_writer

Page 18: Metaprogramação Ruby

class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end

Page 19: Metaprogramação Ruby

class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end

Modificadores de

visibiliade/acesso

Page 20: Metaprogramação Ruby

class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end

Modificadores de

visibiliade/acesso

Attributos da �

classe/instancias

Page 21: Metaprogramação Ruby

class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end

Modificadores de

visibiliade/acesso

Attributos da �

classe/instancias

Page 22: Metaprogramação Ruby

class AttrExamples attr_accessor :accessor attr_reader :reader attr_writer :writer end

Modificadores de

visibiliade/acesso

Attributos da �

classe/instancias

Page 23: Metaprogramação Ruby

Rails Models

class Product < ActiveRecord::Base end

Page 24: Metaprogramação Ruby

Rails Models

class Product < ActiveRecord::Base end

Cadê os atributos?

Cadê o construtor?

Page 25: Metaprogramação Ruby
Page 26: Metaprogramação Ruby

Métodos que definem métodos

§ Definidos na class Module

Page 27: Metaprogramação Ruby

Exemplo: attr_accessor

@attr = nil def attr() @attr end def attr=(attr) @attr = attr end

Page 28: Metaprogramação Ruby

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

Page 29: Metaprogramação Ruby

Como o ruby sabe qual o nome da minha variável?

Vamos pensar um pouco…

Page 30: Metaprogramação Ruby

#define_method

symbol é o nome�do método que vai �ser criado

block é o que esse �novo método vai fazer

Page 31: Metaprogramação Ruby

#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!

Page 32: Metaprogramação Ruby
Page 33: Metaprogramação Ruby
Page 34: Metaprogramação Ruby

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

Page 35: Metaprogramação Ruby

Classes ou Instâncias???

Page 36: Metaprogramação Ruby
Page 37: Metaprogramação Ruby

Nota sobre mapa do objeto

Page 38: Metaprogramação Ruby

Classes são Objetos

§ CONSTANTES são escritas com letras maiúsculas

§ Uma classe é só uma Constante apontando para um objeto do tipo Class

Page 39: Metaprogramação Ruby

Exemplo real #showmethecode

Page 40: Metaprogramação Ruby

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

Page 41: Metaprogramação Ruby

Resolvendo com programação

Controller

Model

Worker

Notifier -sell() notify_client notify_manager notify_app1 -out_of_stock()

EmailHandler

ActiveMQHandler

RestHandler

Page 42: Metaprogramação Ruby

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

Page 43: Metaprogramação Ruby

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

Page 44: Metaprogramação Ruby

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

Page 45: Metaprogramação Ruby

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

Page 46: Metaprogramação Ruby

Melhorando com metaprogramação

Page 47: Metaprogramação Ruby

Analisando a solução

§ Define vários métodos em tempo de execução

§ Código genérico

§ Remove duplicações

§ É muito foda =)

Page 48: Metaprogramação Ruby

Analisando a solução

§ O método nunca ser utilizado

§ Código difícil de ler

§ Complexo

§ É muito foda =(

Page 49: Metaprogramação Ruby

#method_missing

se o ruby não sabe o que fazer ele chama �o method_missing

Page 50: Metaprogramação Ruby

Outra solução com metaprogramação

Page 51: Metaprogramação Ruby

#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

Page 52: Metaprogramação Ruby

Ruby method lookup

Procura no �

objeto

Page 53: Metaprogramação Ruby

Ruby method lookup

Procura no �

objeto Procura na �

classe

Page 54: Metaprogramação Ruby

Ruby method lookup

Procura no �

objeto Procura na �

classe

Procura nas �

superclasses

Page 55: Metaprogramação Ruby

Ruby method lookup

Procura no �

objeto Procura na �

classe

Procura nas �

superclasses

Procura nos �módulos

Page 56: Metaprogramação Ruby

Ruby method lookup

Procura no �

objeto Procura na �

classe

Procura nas �

superclasses

Procura nos �módulos

Procura na �

classe da �

classe

Page 57: Metaprogramação Ruby

Analisando a solução

§ Só executa quando o método é chamado

§ Código genérico

§ Remove duplicações

§ É muito foda =)

Page 58: Metaprogramação Ruby

Analisando a solução

§ Percorre todo o mapa de objetos

§ Código difícil de ler

§ Complexo

§ É muito foda =(

Page 59: Metaprogramação Ruby

Outra solução com metaprogramação

Page 60: Metaprogramação Ruby

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 =)

Page 61: Metaprogramação Ruby

Analisando a solução

§ Código difícil de ler

§ Complexo

§ É muito foda =(

Page 62: Metaprogramação Ruby

Outra possível solução

§ class_eval / instance_eval

§ String -> Código

“def #{event}” +

“ #chama notifiers” +

“end”

§ PERIGO!!!

Page 63: Metaprogramação Ruby
Page 64: Metaprogramação Ruby

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

Page 65: Metaprogramação Ruby

Quais os próximos passos

§ Entender Modelo de Objetos do Ruby

§ Singleton class/Eigenclass

§ Lambdas e Procs

§ Soluções alternativas para metaprogramação

Page 66: Metaprogramação Ruby
Page 67: Metaprogramação Ruby

OBRIGADO! @marcosbrizeno

Geek Night Recife