Onde devemos colocar a ação de pesquisa?
In GET /search/:text
. Isso retornará uma matriz JSON contendo as correspondências, todas as correspondências que contêm o álbum ao qual ele pertence. Isso faz sentido, porque o cliente pode estar interessado não na faixa em si, mas no álbum inteiro (imagine que você esteja procurando por uma música que, você acredita, estava no mesmo álbum que aquela que você lembra do nome).
não será bom retornar os IDs pai com cada um deles. Estou errado?
Faixas individuais podem conter o álbum. Isso garantirá que a representação da faixa seja uniforme se você puder obter uma faixa por meio de um álbum ou por meio de pesquisa (nenhum álbum aqui).
Qual é melhor?
Como afirmado anteriormente, a inclusão do álbum faz sentido. Embora o terceiro ponto (com o URI relativo) possa ser interessante em alguns casos (você não precisa pensar na maneira como o URI deve ser formado), ele tem a desvantagem de não fornecer explicitamente o álbum. O quarto ponto corrige isso. Se você vir o benefício de ter o URI relativo na resposta, poderá combinar os pontos 3 e 4.
Ou talvez eu seja burro?
Escolher URIs bons não é uma tarefa fácil, principalmente porque não existe uma resposta certa. Se você desenvolver o cliente ao mesmo tempo que a API, poderá ajudá-lo a visualizar melhor como a API pode ser usada. Dito isto, outras pessoas podem preferir outros usos em que você não estava pensando ao desenvolver a API.
Um aspecto que pode ser problemático é como você organiza os dados internamente, ou seja, o uso de uma hierarquia. Do seu comentário, você está se perguntando para o que deve conter uma resposta GET /artist/1/album/10/song/3/comment/23
, o que mostra uma visão muito orientada para a árvore. Isso pode levar a alguns problemas ao estender o sistema posteriormente. Por exemplo:
- E se uma música não tiver um álbum?
- E se um álbum tiver vários artistas?
- E se você quiser adicionar um recurso que permita comentar álbuns?
- E se houver comentários de comentários?
- etc.
Este é essencialmente o problema que expliquei no meu blog : uma representação em árvore tem muitas limitações para ser usada efetivamente em muitos casos.
O que acontece se você destruir a hierarquia? Vamos ver.
GET /albums/:albumId
retorna um JSON contendo as meta informações sobre o álbum (como o ano em que foi publicado ou o URI do JPEG mostrando a capa do álbum) e uma matriz de faixas. Por exemplo:
GET /albums/151
{
"id": 151,
"gid": "dbd3cec7-b927-423f-894b-742c4c7b54ce",
"name": "Yellow Submarine",
"year": 1969,
"genre": "Psychedelic rock",
"artists": ["John Lennon", "Paul McCartney", ...],
"tracks": [
{
"id": 90224,
"title": "Yellow Submarine",
"length": "2:40"
},
{
"id": 83192,
"title": "Only a Northern Song",
"length": "3:24"
}
...
]
}
Por que incluo, por exemplo, o comprimento de cada faixa? Porque imagino que o cliente que mostra um álbum possa estar interessado, listando as faixas por título, mas também mostrando a duração de cada faixa - a maioria dos clientes. Por outro lado, não posso mostrar o (s) compositor (es) ou artista (s) de todas as faixas, porque decido que essas informações não são necessárias nesse nível. Obviamente, suas escolhas podem ser diferentes.
GET /tracks/:trackId
retorna as informações sobre uma faixa específica. Como não há mais hierarquia, você não precisa adivinhar o álbum ou o artista: a única coisa que você realmente precisa saber é o identificador da faixa em si.
Ou talvez até não? E se você puder especificá-lo pelo nome GET /tracks/:trackName
?
GET /tracks/Only%20a%20Northern%20Song
{
"id": 83192,
"gid": "8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b",
"title": "Only a Northern Song",
"writers": ["George Harrison"],
"artists": ["John Lennon", "Paul McCartney", "Ringo Starr"],
"length": "3:24",
"record-date": 1967,
"albums": [151, 164],
"soundtrack": {
"uri": "http://audio.example.com/tracks/static/83192.mp3",
"alias": "Beatles - Only a Northern Song.mp3",
"length-bytes": 3524667,
"allow-streaming": true,
"allow-download": false
}
}
Agora olhe mais de perto albums
; O que você vê? Certo, não um, mas dois álbuns. Se você tiver uma hierarquia, não poderá fazer isso (a menos que você duplique o registro).
GET /comments/:objectGid
. Você pode ter visto os GUIDs feios nas respostas. Esses GUIDs permitem identificar a entidade no banco de dados para executar tarefas que podem ser aplicadas a álbuns, artistas ou faixas. Como comentar.
GET /comments/8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b
[
{
"author": {
"id": 509931,
"display-name": "Arseni Mourzenko"
},
"text": "What a great song! (And I'm proud of the usefulness of my comment)",
"concerned-object": "/tracks/83192"
}
]
O comentário faz referência ao objeto em questão, possibilitando acessá-lo fora do contexto (por exemplo, ao moderar os comentários mais recentes GET /comments/latest
).
Observe que isso não significa que você deve evitar qualquer forma de hierarquia na sua API. Há casos em que faz sentido. Como um princípio básico:
Se o recurso não fizer sentido fora do contexto do recurso pai, use a hierarquia.
Se o recurso puder viver (1) sozinho ou (2) em um contexto de recursos pai de tipos diferentes ou (3) ter vários pais, a hierarquia não deve ser usada.
Por exemplo, as linhas de um arquivo não fazem sentido fora do contexto de um arquivo, portanto:
GET /file/:fileId
e:
GET /file/:fileId/line/:lineIndex
Estão bem.
SongSearchResult
tudo bem, eu suponho. Mas o que há com URLs? Devo fornecerparentID
cada objeto e usá-lo como parâmetro GET ou parte normal do URL? E se eu tiver profundidade> 2?/artist/1/album/10/song/3/comment/23
- é uma loucura fornecer todos os id de artista, álbum e música emcomment
objeto, mas ouvi dizer que é um caminho a percorrer, mas não é tão desagradável ?!