Pesquisar

segunda-feira, 14 de janeiro de 2008

REST - Breves esclarecimentos sobre o estilo arquitetural

Primeiro esclarecimento:
REST é um estilo arquitetural (simples assim), que pode ser aproveitado para o desenvolvimento de aplicações que utilizem uma rede de comunicação, o termo foi "inventado" por Roy Fielding na dissertação de Ph.D dele.

Segundo esclarecimento:
REST não é um padrão, especificação, ou seja, você não irá ver a Sun, Microsoft ou IBM vendendo um Toolkit para REST. Simplesmente REST é um estilo arquitetural, você pode compreender-lo e desenvolver seus serviços para web (aplicações, web services ...) nesse estilo.

Um exemplo do uso deste estilo arquitetural (REST)

A Web...
Você deseja um serviço, por exemplo um dicionário online.
Você procura esse dicionário (normalmente usando outro serviço de busca da Web).
Como resposta você obtém uma URL que identifica unicamente aquele recurso (serviço). [ www.dicionariorest.com.br].
Pronto agora você consegue tal serviço.

Um ótimo jeito é dar outro exemplo

Uma empresa Xyz deseja oferecer serviços na web que habilitam seus clientes a:

1 - Obter uma lista de produtos.
2 - Obter informação detalhada sobre um produto.
3 - Comprar usando a Internet.

Como seria o jeito REST de se resolver isto.

O serviço está disponível pela URL (única), no exemplo o cliente do serviço deve usar a URL para ter acesso ao serviço.
www.lojadementira.com.br/produtos
O retorno óbvio é uma lista de produtos (HTML) todavia poderia ser especificado qual o tipo de recurso queriamos, por exemplo.
www.lojadementira.com.br/produtos&tipo=xml
Supondo que o serviço retornasse o seguinte xml:

[?xml version="1.0"?]
[lista]
[produto id=www.lojadementira.com.br/produtos/001][/produto]
[produto id=www.lojadementira.com.br/produtos/002][/produto]
[produto id=www.lojadementira.com.br/produtos/003][/produto]
[produto id=www.lojadementira.com.br/produtos/004][/produto]
[produto id=www.lojadementira.com.br/produtos/005][/produto]
[produto id=www.lojadementira.com.br/produtos/006][/produto]
[/lista]


Não reparem na sintaxe (provavelmente) errada do xml acima. Notem a característica chave do REST: A lista própria já traz como acessar o serviço de detalhes do produto. O cliente se transfere de um estado para o próximo examinando e escolhendo entre as alternativas.

Ótimo agora com a lista, o cliente escolhe o produto [www.lojadementira.com.br/produtos/005] e como retorno obtém um novo xml.

[?xml version="1.0"?]
[produto id=1]
[name] tutorial sobre REST [/name]
[price]18.8[/price]
...
[/produto]

(ps: claro que www.lojadementira.com.br/produtos/005 não é se trata do endereço físico da página html www.lojadementira.com.br/produtos/005.html, é somente um modo de acessar unicamente aquele recurso, todavia essa descrição detalhada do produto pode (e deveria) ser dinâmica.)

Algumas características do REST (baseada em redes)

* Geralmente usam-se interfaces unificadas.
GET, POST, PUT e DELETE par prover serviços.
* Stateless: Toda requisição precisa conter toda informação necessária para atender a requisição.
* Tudo é um recurso e tudo é adiquirido/executado pela URL.


Principios do REST
* Dê a tudo (os recursos) um ID (URI)
* Link tudo
Por exemplo um pedido:
[order self='http://example.com/customers/1234' ]
[amount]23[/amount]
[product ref='http://example.com/products/4554' /]
[customer ref='http://example.com/customers/1234' /]
[/order]


Nesse pedido posso facilmente encontrar os recursos relacionados a ele, como cliente e produto.

* Use métodos padrões


Se tudo é um recurso com identidade...

class Resource {
Resource(URI u);
Response get();
Response post(Request r);
Response put(Request r);
Response delete();
}

Exemplo número 9.001

Supondo as seguintes classes de serviço:

public class ServicoGerenciamentoDeProduto{
+getDetalhesDoProtudo()
+atualizarProduto()
+inserirProduto()
...
}

public class ServicoGerenciamentoDeCliente{
+getTelefoneComercial()
+atualizarCliente()
+inserirCliente()
...
}

Num modo REST de resolução poderia ser criado algo semelhando a isso.

interface Resource{
+GET
+PUT
+POST
+DELETE
}

E fazer as classes de serviço implementarem essa interface (um dos princípios sobre a padronização). Essa implementação é por recurso, normalmente um serviço expõem mais de um recurso.


Desculpem pela quantidade de exemplos mas o assunto é muito "abstrato" ou no mínimo díficil de se explicar, acredito que com exemplos ficará mais claro.

Conclusão.

Francamente gostaria de ter deixado mais claro o que é REST e como aplicar, mas estou achando que não consegui, assuntos sobre estilos arquiteturais são complexos de ser entendidos e explicados. Talvez uma leitura nos links abaixo facilite o entendimento. Enfim usar REST é apenas utilizar melhor o jeito HTTP de ser.


Fontes e bons links:
http://www.xfront.com/
http://www.fragmental.com.br/
http://rest.blueoxen.net/cgi-bin/wiki.pl?BenjaminsRESTTutorial
http://forum.rubyonbr.org/forums/1/topics/2212#posts-12150
http://java.sun.com/developer/technicalArticles/WebServices/restful/
A Brief Introduction to REST by Stefan Tilkov


Ps: não se trata de um tutorial ou faq sobre o assunto. Possivelmente há erros no texto, qualquer correção ou adição de informação será bem-vinda.

sexta-feira, 11 de janeiro de 2008

Um (mal) programador Java aprendendo Ruby - Parte 1

Algumas características interessantes do Ruby fazem algumas tarefas mais rápidas. Em um programa oo para saber se um objeto é uma instância de uma determinada classe.

Em Java:
objeto instanceof Classe

Em Ruby:
objeto.is_a? Classe

Quando desejo usar herança:

Em Java:
public class Filho extends Pai

Em Ruby:
class Filho < Pai

Quando desejo criar um método que retorne a soma entre dois números:

Em Java:
public int soma(int v1, int v2){
return v1 + v2
}

Em Ruby:
def soma(v1,v2)
v1+v2
end

"Lançando exceções".

Em Java:
if (saldo < saque) throw new Exception("Sem fundos!")

Em Ruby:
raise Exception.new("Sem fundos!") unless saldo > saque

Algo que percebo é que as vezes para implementar características em Ruby, gasto menos linhas de código para o mesmo propósito quando usava Java (bem como o código se transforma em algo mais expressivo também). A principio esta característica de escrever menos assusta e logo vêm milhares de perguntas a cabeça como: quando e como retorno o valor... essa tipagem dinâmica, sei não viu... . Bem sobre algumas características (como o retorno do método) o Ruby utiliza algumas convenções:

Ao invés de digitar ; (em Java, C, C++, C#) para quebra de linha apenas usa o Enter para tal.

Ao invés de usar a palavra-chave return [mesmo que você possa utilizar-la] o Ruby entende que seu último comando será o retorno do método, todavia se quiser usar o return poderá também.

Quanto a tipagem dinâmica não sei muito sobre... quando souber posto aqui.

ps: Este post não é de forma alguma um "flamewar" para provar que uma linguagem é melhor do que outra...

quarta-feira, 9 de janeiro de 2008

Ruby: usando classe aberta (open classe)

Extender (não no sentido "carregado" da herança) uma classe já existente.... Interessante recurso, lembro de algo similar no mundo .net os extension methods.

#uma classe já existente.
class Integer

#adicionando métodos a mesma.
def am(*args)
self == 12 ? 0 : self
end

def pm(*args)
self == 12 ? 12 : self +12
end
end


#veja que interessante o uso.
i = 4.pm
puts "4Pm = " << i.to_s #deve aparecer 4Pm = 16
i = 4.am
puts "4Am = " << i.to_s #deve aparecer 4Am = 4

#outro exemplo...
class String
def em_maisculo
self.upcase
end
end

puts "galaxy".em_maisculo



Esse recurso pode facilitar a escrita de interfaces fluente... imagine.
compromisso.adicionar("ler algo sobre ddd").comecando_as(2.Pm).ate_as(4.Pm).hoje()


* Exemplos inspirados numa apresentação de um trabalhador da throughworks.

"Interface fluente" no JavaScript

Isso mesmo "já embutida":
Ao invés de fazer isso.

elemento = document.getElementById("attachments-box");
elemento.removeAttribute("width");

elemento1 = document.getElementById("format_auto");
elemento1.setAttribute("checked", "true");

Você pode fazer diretamente:
document.getElementById("attachments-box").removeAttribute("width");
document.getElementById("format_auto").setAttribute("checked", "true");

E só pra não perder o costume mais um link de um belo exemplo de uma interface fluente: http://gc.blog.br/2007/09/25/refatorando-para-fluent-interface/

sexta-feira, 4 de janeiro de 2008

Expressividade na linguagem

Atualmente existem muitas linguagens de programação no mercado, algumas que fazem parte do "legado" {cobol,natura...} e outras estão em "voga" {java,ruby,c#...}. Fala-se muito em expressividade na escrita de código. A linguagem pode ajudar e muito a criação de código mais expressivo. Como exemplo inicial, duas linguagens, Java já conhecida e admirada e Ruby nova e promissora.
Para se obter o ultimo elemento de uma lista...

Em Java.
aList.get(aList.size -1)
Em Ruby.
anArray.last

É notório que o código parece ser melhor expresso com Ruby.
Agora considere os códigos abaixo:

//C# 2.0
date d = Helper.At(Helper.FromToday(Helper.Days(2)), Helper.Pm(4));
//C# 3.0
date d = 2.Days().FromToday().At(4.Pm);
Veja o quanto a versão 3.0 do sharp é mais fácil de ser "lida".

Outro exemplo:

Em Java:
public List pessoasFisicas(List pessoas) {
List resultado = new ArrayList();
for (Pessoa pessoa : pessoas)
if (pessoa.isFisica()) result.Add(pessoa);
return result;
}

Em Ruby:
def pessoasFisicas(pessoas)
return pessoas.select {|e| e.isFisica}
end

Sem comentário para essa última demonstração.
"Ser expressivo" pode facilitar futuras manutenções, extensões e integrações no código.

Os exemplos foram roubados discaradamente de
* HumaneInterface - Martin Fowler
* Artigo no InfoQ

ps: os códigos podem estar errados.

quinta-feira, 3 de janeiro de 2008

Ótimo post sobre Interface Fluente.

No site abaixo verá um exemplo bastante interessante, principalmente para quem trata requisições (no modelo "JSP/Servelt") em páginas.
http://fragmental.tw/2007/10/18/notes-on-language-adaption/
Enjoy it.