Sem categoria
The REST of us - Parte 03

Para quem não vem acompanhando este é o terceiro post de uma série que pretende cobrir os pontos que, na minha humilde opinião, devem nortear qualquer desenvolvedor que pretende estruturar um serviço web baseado nos princípios do estilo arquitetural REST. No primeiro post falamos das premissas que guiaram o estudo de Roy Fielding e no segundo citamos a lista de restrições e “normas” que sistemas distribuídos devem seguir para serem considerados REST. Contudo, essa lista de restrições ainda deixa uma grande margem para interpretação da arquitetura e desenvolvimento destes sistemas, assim, neste post vamos usar Leonard Richardson e Martin Fowler como base para discutir REST em nivel de implementação em um modelo que eles chamaram “Nivel de maturidade REST”.
Antes de iniciar tenho dois disclaimers importantes. Vamos utilizar os exemplos que Martin usou em seu post, contudo, os exemplos partem da premissa de que você tem uma certa familiaridade com XML o que hoje já não é uma certeza (thank god). Então, se você não faz ideia de como o XML é estruturado vale pena uma lida pelo menos para entender como se dá sua formalização.
O segundo é que em todos os níveis de implementação utilizaremos o mesmo exemplo utilizado por Martin de um usuário fazendo o agendamento de uma consulta e neste caso os passos que vamos seguir serão de consulta dos horários disponíveis em um dia específico e tentativa de cadastro de uma nova consulta em um dos horários disponíveis.

  • Nível 0 – O pântano do POX:

O primeiro nível de implementação REST que eles descrevem é basicamente a quebra arquitetural que discutimos anteriormente como sistemas baseados em RPC ou SOAP e POX, que no titulo se refere a Plain Old XML como forma de indicar, ironicamente, como essas arquiteturas trabalham.
Neste primeiro nível essas arquiteturas utilizam o HTTP basicamente como um sistema de transporte e exposição de seus métodos sem utilizar as demais partes do protocolo, assim, criando uma certa disparidade entre o protocolo utilizado e sua implementação.
Neste nível o serviço deve expor um URI onde a ação de consulta deve ocorrer. Em nosso exemplo vamos utilizar o mesmo endpoint para consulta dos horários disponíveis e de cadastro de uma nova consulta, contudo, isso seria uma definição da aplicação, o que por si só já é um problema.

Level 0

Nível 0 – O pântano do POX

Assim, para este nível a comunicação de daria nestes termos:

  • Requisição

POST /appointmentService HTTP/1.1
[demais headers]

  • Resposta

HTTP/1.1 200 OK
[various headers]

<openSlotList>
<slot start = "1400" end = "1450">
<doctor id = "mjones"/>
</slot>
<slot start = "1600" end = "1650">
<doctor id = "mjones"/>
</slot>
</openSlotList>

Com os horários disponíveis o próximo passo seria a tentativa de marcar uma consulta:

  • Requisição

POST /appointmentService HTTP/1.1
[demais headers]

<appointmentRequest>
<slot doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
</appointmentRequest>

  • Resposta

HTTP/1.1 200 OK
[demais headers]

<appointment>
<slot doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
</appointment>

Como já apontamos neste primeiro nível trabalhamos com um sistema baseado em RPC comunicando XML entre as partes, mas, poderia ser qualquer outro tipo de formatação de dados como JSON e YAML. Em sistemas baseados em RPC uma serie de métodos é exposta para acesso pelo cliente, contudo, o sistema não segue nenhuma padronização formal ou organizacional para dar unidade entre os processos e demais serviços. Assim indo de encontro a várias das premissas definidas por Roy Fielding como Escalabilidade, Simplicidade, Visibilidade, Portabilidade e Performance.

  • Nível 1 – Recursos

Se você vem acompanhando a série de post’s até aqui um conceito com o qual você já deve estar familiarizado é o de recursos, mas vamos dar uma passada sobre este que é um dos grandes pilares da arquitetura. REST significa Transferência de Estado Representativo (Representational State Transfer) que em termos gerais significa que o que é transferido entre cliente e servidor é uma representação do estado de algo e este, para Roy, é o recurso. Recursos, contudo, são abstrações do que podem ser documentos/entradas de um banco, serviços de processamento de dados e etc. Assim, o importante aqui é a mudança de mindset de um estilo arquitetural que expõe métodos para um que expõe recursos.

Level 1

Nível 1 – Recursos

  • Requisição

POST /doctors/mjones HTTP/1.1
[demais headers]

<openSlotRequest date = "2010-01-04"/>

  • Resposta

HTTP/1.1 200 OK
[various headers]

<openSlotList>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
<slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

No primeiro passo agora tratamos o médico como um recurso que pode ser acessado por identificador único(URI) “/doctors/mjones” e daqui por diante cada recurso vai ser acessado individualmente.

  • Requisição

POST /slots/1234 HTTP/1.1
[demais headers]

<appointmentRequest>
<patient id = "jsmith"/>
</appointmentRequest>

  • Resposta

HTTP/1.1 200 OK
[various headers]

<appointment>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
</appointment>

Assim, trabalhando com recursos, na categorização de Leonard, damos o primeiro passo em direção à adequação a REST e com ele começamos a atender várias das premissas de Roy como Escalabilidade, Simplicidade, Visibilidade, Portabilidade e Performance bem como começamos a atender a maior e mais restritiva de suas regras: a Interface regular.

  • Nível 2 – HTTP (Verbos, Status)

Neste nivel Leonard evidencia o uso do HTTP com maior propriedade em contraponto aos exemplos anteriores onde o protocolo atua apenas como um condutor de informação, que é estruturada e organizada por estruturas externas de dados. Em ambos os exemplos foram utilizados somente o verbo POST, que é o mais comum para sistemas baseados em RPC, contudo poderiam ter sido usados os demais verbos, pois aqui eles não cumprem nenhum papel funcional de apontar para o servidor qual o caráter da interação.

Level 2

Nível 2 – HTTP (Verbos, Status)

  • Requisição

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

  • Resposta

HTTP/1.1 200 OK
[various headers]

<openSlotList>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
<slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

Já tratamos anteriormente sobre os verbos existentes e seus significados na versão 1.1 do protocolo HTTP no post anterior, contudo nos exemplos de Martin há uma outra mudança na comunicação. Utilizando o verbo GET para obter os dados sobre o médico específico Martin optou por não passar os informações para a filtragem, data e estado, pelo corpo da requisição. Esta é uma prática aconselhada pela natureza do método definido na especificação, pois, GET em sua definição é uma chamada que não atua diretamente sobre o recurso, assim, URI’s diferentes devem retornar recursos diferentes ou até mesmo estados diferentes de um mesmo recurso. Outro motivo importante é que como no HTTP trabalhamos com responsabilidade dividida em termos de cache, assim distribuidores intermediários não conseguiriam armazenar informações precisas pois requisições sobre um mesmo recurso estariam esperando respostas diferenciadas.

  • Requisição

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
<patient id = "jsmith"/>
</appointmentRequest>

  • Resposta

HTTP/1.1 201 Created
Location: slots/1234/appointment
[various headers]
<appointment>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
</appointment>

  • Nível 3 – Controles de hipermídia

Quando iniciamos este post falamos que iríamos discutir REST em termos de implementação. Nos dois primeiros níveis nem poderíamos considerar arquiteturas baseadas em REST pois ambas quebram a mais importante regra da arquitetura e no terceiro nível exemplificamos REST com uso do HTTP em sua forma mais sintética. Vale lembrar que quando falamos de arquiteturas em geral tratamos de uma série de regras e preceitos que devem ser seguidos para alcançar as premissas definidas, porém, dentro dessas definições temos margem para implementações que atendam melhor certas aplicações.
Aqui vamos discutir alguns dos pontos de maior confusão quando se trata de REST, HATEOAS (Hypermedia as the Engine of Application State), que diz que um cliente interage com um servidor exclusivamente através de hipermídias fornecidas dinamicamente pelo servidor, assim, sem a necessidade de conhecer qualquer regra de negocio ou relacionamento entre os recursos. Uma vez implementada, o cliente precisa conhecer apenas um único ponto de entrada para um serviço REST e toda interação dar-se-á por links gerados pelo servidor criando, assim, uma árvore dinâmica de interações.

Level 3

Nível 3 – Controles de hipermídia

  • Requisição

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

  • Resposta

HTTP/1.1 200 OK
[various headers]

<openSlotList>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450">
<link rel = "/linkrels/slot/book"
uri = "/slots/1234"/>
</slot>
<slot id = "5678" doctor = "mjones" start = "1600" end = "1650">
<link rel = "/linkrels/slot/book"
uri = "/slots/5678"/>
</slot>
</openSlotList>

Aqui temos a definição de um novo elemento atrelado aos espaços na agenda do médico em questão e esses elementos devem nos apontar exatamente o que deve ser feito para o agendamento. Assim, estes links não só nos apontam onde devemos executar as próximas ações como também nos indicam quais as ações possíveis a cada passo dentro do processo, assim, aqui depois da consulta dos horários disponíveis para um médico poderíamos exclusivamente agendar um horário.

  • Requisição

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
<patient id = "jsmith"/>
</appointmentRequest>

  • Resposta

HTTP/1.1 201 Created
Location: http://royalhope.nhs.uk/slots/1234/appointment
[various headers]

<appointment>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
<link rel = "/linkrels/appointment/cancel"
uri = "/slots/1234/appointment"/>
<link rel = "/linkrels/appointment/addTest"
uri = "/slots/1234/appointment/tests"/>
<link rel = "self"
uri = "/slots/1234/appointment"/>
<link rel = "/linkrels/appointment/changeTime"
uri = "/doctors/mjones/slots?date=20100104@status=open"/>
<link rel = "/linkrels/appointment/updateContactInfo"
uri = "/patients/jsmith/contactInfo"/>
<link rel = "/linkrels/help"
uri = "/help/appointment"/>
</appointment>

Os benefícios do uso de controles de hipermídia são bem claros, desacoplando cliente e servidor qualquer alteração na lógica de negócio, relação entre as entidades e ações suportadas não quebraria as operações no cliente. Além disso, ajuda o cliente na navegação dentro do mesmo serviço abrindo um leque de opções para as próximas ações.
Ainda não existe um padrão sólido de como são especificadas as relações entre recursos em REST, contudo, alguns drafts já foram feitos e em seu artigo Martin utilizou o RFC 4287, porém atualmente muitos indicam o RFC 5988 como referência para ligações dinâmicas e relações hipermídia.

  • Conclusão

Assim como Martin descreveu em seu post aqui vale o disclaimer de que os níveis descritos por Leonard não são níveis da definição de REST, contudo, arquiteturas ganham definições ao longo de sua vida útil, mas como foi Roy que formalizou sua definição e cunhou o termo a sua sempre ganha mais peso.
Assim, os níveis devem ser utilizados como guia processual de implementação REST e até mesmo como um método de compartimentar suas várias restrições ajudam a desenvolver e até mesmo migrar serviços para este estilo arquitetural.

Sobre o autor

Diogo Reus

Diretor de vendas e completamente apaixonado por construir empresas melhores! Inclusive a nossa.

O que achou? Comente aqui :)

Comentário enviado para moderação!

Erro ao enviar a mensagem, tente novamente!

Se você gostou deste, pode gostar também...

QUIZ: A sua área de desenvolvimento analisa a performance dos treinamentos?
Conheça dicas de 3 profissionais sobre a carreira em treinamento e desenvolvimento
ROI em T&D: Como analisar resultados pode fazer a sua área crescer