Modelagem dos serviços
Nesta seção falaremos da modelagem e desenvolvimento dos serviços utilizando REST. Para ilustrar bem os cenários abordados, trabalharemos em cima de um problema proposto: um processo de leilão do Mercado Livre.
Apresentação do problema
O problema que buscaremos resolver envolve serviços referentes a um processo de leilão do Mercado Livre. Num leilão típico, um usuário cadastrado no site coloca para venda um produto (novo ou usado), definindo um valor para o lance inicial e então aguarda pelas ofertas de compra por parte de outros usuários interessados no produto.
Após receber algumas ofertas pelo produto, em um determinado momento o vendedor decide aceitar a melhor oferta recebida, e então vende o produto para o comprador que fez esta oferta, encerrando neste momento o leilão. Em seguida à venda, ocorrem os trâmites de pagamento e entrega do produto (que não trataremos aqui) e no final, vendedor e comprador avaliam um ao outro, o que é essencial para os usuários sentirem maior segurança ao realizar negociações futuras deste gênero.
Na modelagem desta aplicação, quatro entidades serão utilizadas: Usuário, Item, Oferta e Avaliação.
Modelagem com Recursos
O ponto de partida do desenvolvimento com REST é definir quais são os recursos envolvidos, com base nos requisitos do sistema e nos serviços que se deseja oferecer. No nosso exemplo, esta etapa não é complexa. Os recursos que manipularemos são: Usuario, Item, Oferta e Avaliacao.
Embora esta identificação tenha sido trivial no domínio que definimos, em alguns casos este processo pode ser um dos mais complexos na modelagem da aplicação. De uma maneira geral, quanto mais a aplicação se aproxima de um CRUD, mais fácil é a identificação dos recursos.
Para este processo de leilão, os serviços que disponibilizaremos serão os da Tabela 1:
|
Serviço |
Descrição |
|
Anunciar item |
Permite que um usuário coloque um produto à venda. |
|
Buscar itens do vendedor |
Pesquisa os itens à venda de um vendedor. |
|
Cadastrar usuário |
Realiza o cadastro de um novo usuário no site. |
|
Realizar oferta |
Permite que um comprador faça uma oferta por um produto. |
|
Retirar oferta |
Permite a remoção de uma oferta por parte do comprador. |
|
Buscar ofertas do item |
Pesquisa por todas as ofertas feitas sobre um produto. |
|
Buscar melhor oferta |
Busca a melhor oferta feita até o momento sobre um produto. |
|
Aceitar melhor oferta |
Permite que um vendedor aceite a melhor oferta feita sobre o seu produto, e com isso encerre o leilão do mesmo. |
|
Avaliar usuário |
Realiza a avaliação de um usuário por parte de outro usuário, após o término do processo de compra. |
|
Buscar avaliações do usuário |
Pesquisa por todas as avaliações recebidas por um usuário. |
Tabela 1. Serviços oferecidos para interação com o processo de leilão.
Protocolo de comunicação REST
Tendo definido os recursos e os serviços que precisamos oferecer, é necessário definir as manipulações possíveis sobre os recursos existentes. Esta etapa é a tradução de operações de negócio em interações diretas sobre usuários, ítens, ofertas e avaliações. Esta tradução feita explorando os recursos do HTTP nos levará a um conjunto de URIs que a aplicação oferece para os clientes.
Para elaborar um bom protocolo de comunicação REST, devemos pensar em algumas questões importantes, como estas:
- Quais são os recursos?
- Quais são as URIs?
- Quais são os formatos manipulados?
- Que métodos HTTP são aceitos em cada URI?
- Que status HTTP deve ser retornado em cada situação?
- Que cabeçalhos HTTP são relevantes em cada situação?
A definição das URIs e dos métodos HTTP aceitos é primordial para um protocolo REST com clareza e de fácil utilização e extensão. Ao ler as URIs já devemos ser capazes de entender quais são os recursos presentes nas mesmas, e o casamento delas com os métodos HTTP deve ser intuitivo.
A Tabela 2 descreve todas as URIs disponíveis na aplicação e quais métodos HTTP podem ser invocados em cada uma delas. Além disso, são especificados os recursos manipulados por cada requisição e o efeito que uma determinada chamada exerce sobre os recursos existentes.
|
URI |
Método |
Formato |
Efeito |
|
/item/{id} |
GET |
Item |
Busca um item. |
|
PUT |
Item |
Atualiza um item. | |
|
/item/{id}/ofertas |
GET |
Coleção de ofertas |
Busca ofertas feitas sobre um item. |
|
POST |
Oferta |
Adiciona oferta a um item. | |
|
/oferta/{id} |
GET |
Oferta |
Busca uma oferta. |
|
PUT |
Oferta |
Atualiza uma oferta. | |
|
DELETE |
- |
Remove uma oferta. | |
|
/usuario |
POST |
Usuario |
Cadastra um usuário. |
|
/usuario/{id} |
GET |
Usuario |
Busca um usuário. |
|
PUT |
Usuario |
Atualiza um usuário. | |
|
/usuario/{id}/avaliacoes |
GET |
Coleção de avaliações |
Busca as avaliações recebidas por um usuário. |
|
/usuario/{id}/itens |
GET |
Coleção de ítens |
Busca os ítens anunciados por um determinado usuário. |
|
POST |
Item |
Usuário coloca novo item à venda. | |
|
/avaliacao/{id} |
GET |
Avaliação |
Busca uma determinada avaliação. |
|
/avaliacao/de/{id}/para/{id} |
POST |
Avaliação |
Realização da avaliação de um usuário sobre outro. |
|
/services |
GET |
Coleção de URIs |
Consulta URIs e métodos HTTP disponíveis para acesso. |
April 24th, 2009 at 12:36 am
Olá Bruno,
Primeiramente parabéns pelo artigo! Arrisco a dizer que, dentre os tupiniquins, é o mais útil que encontrei até o momento pois ele é pragmático e contém um exemplo abrangente.
Agora a questão. No caso exposto, se fizesse sentido consultar Itens independente de qual Usuário:
1) o aconselhável seria eu ter /itenS e descartar /item e /usuario/{id}/itens?
2) ou poderiam ser preservados /itens e /usuario/{id}/itens?
3) ou deveria ter apenas /itens para ter somente uma URI para um tipo de recurso?
Há alguma diretriz dentros dos princípios REST que fala sobre isso?
Valeu!
[]s
Shigueru.
April 24th, 2009 at 7:20 am
Oi Shigueru, agradeço pelos comentários, e fico feliz que tenha lhe ajudado.
Sobre a sua pergunta: você poderia criar uma nova URI /itens e manter as anteriores, não vejo problemas. Entretanto, eu escolheria usar um mesmo prefixo para os recursos de item. A escolha de usar singular ou plural é livre, mas eu prefiro usar apenas um dos 2 para cada recurso.
Assim, você poderia usar:
/itens/{id} e /itens?faixa=40-60 ou
/item/{id} e /item?faixa=40-60
Este parâmetro faixa que eu coloquei é com objetivo de paginação de resultados. Eu não gosto de usar query strings na IDENTIFICAÇÃO dos recursos, mas para FILTRAGEM dos resultados acaba sendo conveniente.
April 24th, 2009 at 10:52 am
Valeu pela resposta Bruno!
Já abusando da sua boa vontade, tenho notado que REST não é tão conhecido quanto SOAP, apesar do tempo de estrada que ele já tem. Dessa forma é comum encontrar barreiras a sua adoção. O contraponto mais comum que ouço é “Por que não apenas fazer um POX/HTTP?”. Daí, contando apenas com bagagem teórica digo o porquê da utilização dos códigos HTTP, dos verbos corretos, da utilização de hypermedia, etc.
Mas queria saber de você, Bruno, que já tem experiência prática, se a adoção dos princípios REST realmente facilitam as coisas? Quero acreditar que sim, já que em várias situações vejo REST como mais apropriado do que SOAP e POX/HTTP. Você poderia apresentar quais são os principais beneficios em casos reais?
E os projetos Jersey e RESTeasy, tem ajudado a tirar essa imagem de que REST é mais difícil do que POX/HTTP?
Valeu!
[]s
Shigueru
April 24th, 2009 at 5:43 pm
Oi Shigueru, creio que atualmente REST já é praticamente tão conhecido como SOAP, e em alguns segmentos já é muito mais utilizado.
Sobre o uso de XML sobre HTTP (POX), há muita gente que já usou e teve ganhos com isso. Você não precisa ter um design RESTful para ter software de qualidade.
Entretanto, um aspecto muito importante da adoção de um modelo RESTful sobre POX é a consistência entre implementações. Você acha mais fácil alguém se familiarizar com um protocolo POX ou com um protocolo RESTful que segue várias práticas conhecidas? Consistência é importante quando você precisa ter novas pessoas envolvidas com sua aplicação, e quando você precisa se integrar com outras aplicações.
Comparando REST com SOAP e POX, eu acho especialmente vantajoso usar REST se você pode ter interações de humanos com os seus recursos. O fato de você poder expôr um recurso como JSON e consumir via Ajax, a facilidade de fazer mashups, navegação entre recursos. Você tem um poder enorme, sem ter obrigação de introduzir nenhuma complexidade adicional ao problema em questão.
Mas o fato é que eu não tento convencer ninguém a usar REST (ou qualquer outra coisa). Cada um tem suas escolhas e preferências de tecnologia, e eu prefiro não impôr as minhas a ninguém
April 27th, 2009 at 1:46 pm
Boa Bruno!
Consistência entre implementações através de práticas conhecidas traduz-se em vários ganhos. Dentre elas, destaco o ganho de qualidade.
Sobre convencer alguém ou não, acredito que toda busca por algo melhor e que seja bem fundamentada é válida. E o processo de persuasão é parte natural do processo. Entenda-se persusão como o Despertar para algo melhor.
Agradeço pelos ensinamentos!
[]s
Shigueru.