Restfulie

Caros, com base no short samples do restfulie: http://restfulie.caelum.com.br/restful_rails/short_samples

Se eu tenho esse código no cliente do serviço:
order = Order.from_web resource_uri

E esse código no server:
class Order < ActiveRecord::Base

acts_as_restfulie do |transitions|
transitions << [:show]
transitions << [:destroy] if can_cancel?
transitions << [:controller => :payments, :action => :create, {:id => id}] if can_pay?
end
end

Então, eu vou ter q ter a classe Order nos dois projetos! Isso não quebra a “First Law of Distributed Object Design: Don’t distribute your objects (Fowler)”???

Ola Joel

Quando o Fowler diz isso, ele esta falando de acessar o objeto de outra maquina, e nao se a classe vai estar repetida ou nao nos dois lugares.

Alias, pra chamada ser realmente remota, a classe nao estara repetida, no micro cliente ela sera um stub/proxy dinamica. Quando ele escreveu isso, ele quer que voce evite que objetos que contenham metodos de granularidade fina sejam chamados, pois ai voce tem muitas vezes um grande overhead. Voce precisa desenhar bem seus metodos para que eles tenham a granularidade “exata” para que nao caia em problemas de n+1 requisicoes em vez de um numero fixo de equisicoes.

Esse problema aparece exatamente igual em qualquer tecnologia remota: webservices, ejb, rmi, etc. Se voce escreve um webservice soap/wsdl cheio de operacoes que fazem pequenos gets, vai ter o memo problema. Fowler escreveu isso com os EJBs em mente, quanto as pessoas começaram a usar EntityBeans remotos e a invocar getters remotos: overhead gigante.

Eu acho que vc precisa da classe Order no cliente e no servidor. Isso foi o que percebi a primeira vez que vi o restfulie. Tecnologias de objetos distribuidos pelo menos oferecem transparencia sobre a localidade da implementação. Voce so precisa repetir a interface. No caso do Restfulie não há essa transparência e sim redução de visibilidade.

sem dúvida, é um dos preços pagos por ser inguagem dinâmica, mas nao tem relacao com a lei do Fowler.

Tem como eu baixar o source dos live_examples (http://restfulie.caelum.com.br/restful_rails/live_examples)?

Achei :slight_smile:


sem dúvida, é um dos preços pagos por ser inguagem dinâmica, mas nao tem relacao com a lei do Fowler.[/quote]

Não entendi o que isso tem a ver com a linguagem ser dinamica ou estatica.

Estava falando sobre a necessidade de ter uma classe Order em dois lugares. Order não é um tipo de dado REST, e sim um tipo da aplicação. Só estava questionando se há um motivo especia para um cliente REST possuir o conhecimento de como lidar com uma Order previamente, na forma de uma classe, e não hProduct num documento XHTML, por exemplo.

Ficou mais claro quando vi o código da classe Order.

No cliente:

class Order < ActiveRecord::Base uses_restfulie end

No server:

[code]class Order < ActiveRecord::Base

acts_as_restfulie do |order, transitions|
transitions << :execute_it if (order.status == “preparing”) && order.paid_one_minute_ago?
transitions << [:thanks, { :action => :thanks }] if order.status == "received"
end

has_and_belongs_to_many :trainings
has_many :payments

state :unpaid, :allow => [:latest, :pay, :cancel]
state :cancelled, :allow => :latest
state :received, :allow => [:latest, :check_payment_info]
state :preparing, :allow => [:latest, :check_payment_info]
state :ready, :allow => [:latest, :receive, :check_payment_info]# do |order|

order.paid_one_minute_ago?

end

transition :check_payment_info do |order|
   {:controller => :payments, :action => :show, :order_id => order.id, :payment_id => order.payments[0].id, :rel => "check_payment_info"}
end
transition :latest, {:action => :show}, {:not_found => 404, :no_change => 304}

transition :cancel, {:action => :destroy}, :cancelled
# 405 ==> (dont do it)
# 409 ==> (try again)
# order.status==“cancelled”… trying to cancel ==> 405
# order.status==“preparing”… trying to update it ==> 409
# order.status==“unpaid”… invalid data supplied ==> 400?
transition :pay, {}, :preparing
transition :receive, {}, :received
transition :execute_it, {}, :ready

def paid_one_minute_ago?
# takes one minute to be prepared
self.paid_at < (Time.now - 1.minute)
end

def pay(payment)
debugger
move_to :pay
self.paid_at = Time.now
@payment = payment
@payment.order = self
end

def total_price
total = 0
@trainings.each do |x|
total += x.price
end
total
end

def paid?
payments.size > 0
end

# def can_cancel?
#   raise 405 if @status == :cancelled
#   # ...
# end

end[/code]

Essa classe stub no cliente ainda não me parece uma boa ideia… Acredito que existe uma forma melhor mas ainda não sei como… :slight_smile:
Vou ver como ficaria isso em Java. Vi um exemplo onde o NetBeans gera a classe JavaScript stub a partir de uma serviço REST. Acho isso muito SOAP!!! Onde está o desacoplamento se preciso gerar o cliente caso alguma mudança seja feita no server?

[quote=joellobo]

Essa classe stub no cliente ainda não me parece uma boa ideia… Acredito que existe uma forma melhor mas ainda não sei como… :slight_smile:
Vou ver como ficaria isso em Java. Vi um exemplo onde o NetBeans gera a classe JavaScript stub a partir de uma serviço REST. Acho isso muito SOAP!!! Onde está o desacoplamento se preciso gerar o cliente caso alguma mudança seja feita no server?[/quote]

Ola Joel

Assim como em EJB, em WSDL, ou mesmo um Stub javascript, se voce mudar o servidor e gerar uma quebra de contrato (retirar uma operação/metodo por exemplo) vai sem duvida afetar seu cliente. Nao ha magica. O restfulie ja faz algo muito melhor que as outras tecnologias remotas: se sua interface aumentar no servidor, e voce expor novas mudancas de estado, sem quebrar o contrato anterior, voce nao precisa mudar uma virgula no seu cliente.

Voce tem razao: o modo do netbeans, de gerar o stub, vai na contra mao: voce vai precisar regera-lo se o servico rest mudar. No restfulie o stub inteiro é gerado dinamicamente, e nao ha o problema de compile time, por causa da linguagem ser dinamica.

Mochuara, quis dizer que, com o Ruby, nao da pra gente fazer algo bonito como exportar uma interface. O outro lado precisa ser uma classe, mas vale lembrar que so precisa de um uses_restfulie

Oi pesosoal tudo bem?

Criar um modelo que representa o que você espera é uma coisa, copiar os arquivos do remoto para o local é outra.
De qualquer maneira, o Restfulie não depende da criação de seu modelo no cliente, as docs tem alguns exemplos assim:

order = Restfulie.at(uri).get

ou ainda

Restfulie.at(uri)create {:amount =>500}.to_xml

Nenhum dos dois casos usa um modelo fixo no cliente!

Abraço!

[quote=Guilherme Silveira]Oi pesosoal tudo bem?

Criar um modelo que representa o que você espera é uma coisa, copiar os arquivos do remoto para o local é outra.
De qualquer maneira, o Restfulie não depende da criação de seu modelo no cliente, as docs tem alguns exemplos assim:

order = Restfulie.at(uri).get

ou ainda

Restfulie.at(uri)create {:amount =>500}.to_xml

Nenhum dos dois casos usa um modelo fixo no cliente!

Abraço![/quote]

No caso do primeiro exemplo order seria um map?

[quote=Paulo Silveira]
Mochuara, quis dizer que, com o Ruby, nao da pra gente fazer algo bonito como exportar uma interface. O outro lado precisa ser uma classe, mas vale lembrar que so precisa de um uses_restfulie [/quote]

A falta de visibilidade que estava me referindo é com o fato do cliente depender de um código implementado em Java ou Ruby para saber como o resource pode ser manipulado, ao invés de elementos de dados padrão do REST como media types.

[quote=Guilherme Silveira]Oi pesosoal tudo bem?

Criar um modelo que representa o que você espera é uma coisa, copiar os arquivos do remoto para o local é outra.
De qualquer maneira, o Restfulie não depende da criação de seu modelo no cliente, as docs tem alguns exemplos assim:

order = Restfulie.at(uri).get

ou ainda

Restfulie.at(uri)create {:amount =>500}.to_xml

Nenhum dos dois casos usa um modelo fixo no cliente!

Abraço![/quote]

Putz, era simplesmente isso que eu estava falando mas ainda não tinha visto que o restfulie fazia!!! Show de bola!!!

Sem mais perguntas, meritíssimo :stuck_out_tongue:

[quote=mochuara]
No caso do primeiro exemplo order seria um map?[/quote]

Mais ou menos… é um objeto que se comporta como um map, mas mais malandro… com acesso a resposta e requisicao web etc.

Para não perder a visibilidade etc você pode registrar handlers para seu próprio media type usando o Restfulie::MediaType.register se não me engano (estou sem o codigo agora)!

É o nível de elegancia do REST que quase ninguém faz e ainda é nebuloso pra quase todo mundo, mas tá lá pra ser usado, acredito eu…

Abraço

[quote=joellobo][quote=Guilherme Silveira]Oi pesosoal tudo bem?

Criar um modelo que representa o que você espera é uma coisa, copiar os arquivos do remoto para o local é outra.
De qualquer maneira, o Restfulie não depende da criação de seu modelo no cliente, as docs tem alguns exemplos assim:

order = Restfulie.at(uri).get

ou ainda

Restfulie.at(uri)create {:amount =>500}.to_xml

Nenhum dos dois casos usa um modelo fixo no cliente!

Abraço![/quote]

Putz, era simplesmente isso que eu estava falando mas ainda não tinha visto que o restfulie fazia!!! Show de bola!!!

Sem mais perguntas, meritíssimo :stuck_out_tongue:

[/quote]
Sem problemas, precisando de algo, pode perguntar aqui em portugues ou na lista em ingles, como achar melhor!