Ao projetar um serviço da Web RESTful, a API deve ser projetada para funcionar com o ID de Strings para valores passados entre o servidor?
Aqui está um exemplo: digamos que eu tenho um recurso Employee, que possui atributos de status e de gênero. No banco de dados, Status e Gênero, separa as tabelas e, assim, separa o objeto Domínio, cada um com seu próprio identificador.
Digamos que a solicitação do cliente / funcionário / 1. Não servidor pode retornar algo como estes ....
Caso 1:
{
"id": 1,
"firstName": "Jane",
"lastName": "Doe",
"active": true,
"gender": {
"id": 1,
"gender": "FEMALE"
},
"status": {
"id": 3,
"status": "FULL_TIME"
}
}
Caso 2:
{
"id": 1,
"firstName": "Jane",
"lastName": "Doe",
"active": true,
"gender": "FEMALE",
"status": "FULL_TIME"
}
Caso 3:
{
"id": 1,
"firstName": "Jane",
"lastName": "Doe",
"active": true,
"genderId": 1,
"statusId": 3
}
O caso 3 parece fazer menos sentido, pois o cliente não tem idéia do que é genderId 1, a menos que ele se vire e faça outra chamada ao servidor para obter esses dados.
No entanto, agora digamos que o cliente esteja atualizando o usuário através de:
PUT /employee/1
A carga útil da solicitação deve usar os IDs ou uma string? De qualquer forma, o back-end precisa procurá-los para garantir que sejam válidos, mas é melhor trabalhar com IDs sobre Strings.
fonte
O caso 2 é a única opção real. Você já apontou os problemas do Caso 3. O Caso 1 fornece informações de que o cliente da API não se importa (os IDs internos para status, por exemplo) e exige que o cliente conheça aqueles para construir uma solicitação PUT . Sim, a solicitação PUT é um pouco mais concisa se puder usar os IDs em vez das seqüências completas, mas especificar "FULL_TIME" ou "PART_TIME" é o que o cliente sabe, não que eles tenham alguns IDs arbitrários no banco de dados .
Obviamente, você pode documentar os IDs na documentação da API, mas é igualmente fácil documentar os valores válidos que as seqüências de caracteres têm permissão e provavelmente mais claras.
fonte
Dados enumerados como os que você tem aqui são altamente armazenáveis em cache. Use links em vez de objetos. Use cabeçalhos de cache para permitir que os clientes armazenem em cache gêneros e status localmente, por 24 horas. Somente a primeira chamada do dia sai da máquina do cliente. Provavelmente, você também pode configurar o cache para permitir que servidores intermediários retenham as informações, portanto, algumas solicitações de clientes nem chegam ao seu servidor.
Uma desvantagem é que
/genders/1
não é legível por humanos. Em vez disso/genders/female
, você pode usar , mas nunca pode mudar o nome de um gênero sem quebrar os clientes. Essa é a chave sintética x troca de chave natural - flexibilidade versus legibilidade humana.Você também pode considerar colocar todas as suas listas de valores em um terminal comum, como
Isso esclarecerá aos clientes que todos são basicamente pares de valores-chave que pertencem a diferentes agrupamentos.
fonte
Eu usaria algo entre 1 e 2, pelos motivos que David mencionou:
Você não deseja expor o ID das coisas, a menos que seja necessário.
No entanto, a exposição do ID pode se tornar necessária em algum momento. Se isso acontecer, a compatibilidade com versões anteriores é uma preocupação. Então, eu faria isso:
Que possui as mesmas propriedades da opção 2; mas tem o benefício de que adicionar o ID posteriormente não introduz uma quebra de BC:
Como Eric aponta nos comentários, isso ainda usa o nome da entidade como um identificador uniqe. Se o ID for introduzido posteriormente, o nome ainda deverá permanecer o mesmo, porque os clientes mais antigos poderiam (ou melhor, terão ) codificado para ele.
fonte
name
para consultar e atualizar.id
como identificador exclusivo, isso é uma mudança radical.