Gdzie powinniśmy umieścić akcję wyszukiwania?
W GET /search/:text
. Zwróci tablicę JSON zawierającą dopasowania, każde dopasowanie zawierające album, do którego należy. Ma to sens, ponieważ klient może nie być zainteresowany samym utworem, ale całym albumem (wyobraź sobie, że szukasz utworu, który Twoim zdaniem znajdował się w tym samym albumie, co ten, w którym pamiętasz nazwę).
zwracanie identyfikatorów nadrzędnych za każdym razem nie będzie tak dobrze. Czy się mylę?
Poszczególne utwory mogą zawierać album. Zapewni to jednolitość reprezentacji ścieżki, jeśli można ją uzyskać za pośrednictwem albumu lub wyszukiwania (brak albumu tutaj).
Który jest lepszy?
Jak już wspomniano, włączenie albumu ma sens. Podczas gdy trzeci punkt (z względnym URI) może być interesujący w niektórych przypadkach (nie musisz myśleć o tym, jak powinien zostać utworzony URI), ma on wadę polegającą na tym, że nie podajesz wyraźnie albumu. Czwarty punkt to poprawia. Jeśli zauważysz zaletę posiadania względnego identyfikatora URI w odpowiedzi, możesz połączyć punkty 3 i 4.
A może jestem głupi?
Wybór dobrych URI nie jest łatwym zadaniem, zwłaszcza że nie ma jednej właściwej odpowiedzi. Jeśli rozwijasz klienta w tym samym czasie co interfejs API, może to pomóc w lepszej wizualizacji sposobu użycia interfejsu API. To powiedziawszy, inne osoby mogą wtedy preferować inne zastosowania, o których nie myślałeś podczas tworzenia interfejsu API.
Problemem może być sposób wewnętrznej organizacji danych, tj. Wykorzystanie hierarchii. Po twoim komentarzu zastanawiasz się, na co powinna zawierać odpowiedź GET /artist/1/album/10/song/3/comment/23
, która pokazuje wizję bardzo zorientowaną na drzewo. Może to prowadzić do kilku problemów przy późniejszym rozszerzaniu systemu. Na przykład:
- Co jeśli utwór nie ma albumu?
- Co jeśli album ma kilku wykonawców?
- Co jeśli chcesz dodać funkcję, która umożliwia komentowanie albumów?
- Co jeśli powinny być komentarze do komentarzy?
- itp.
Zasadniczo jest to problem, który wyjaśniłem na moim blogu : reprezentacja drzewa ma zbyt wiele ograniczeń, aby można go było skutecznie wykorzystać w wielu przypadkach.
Co się stanie, jeśli zniszczysz hierarchię? Zobaczmy.
GET /albums/:albumId
zwraca JSON zawierający meta informacje o albumie (takie jak rok wydania lub URI JPEG pokazujący okładkę albumu) oraz tablicę utworów. Na przykład:
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"
}
...
]
}
Dlaczego podaję na przykład długość każdej ścieżki? Ponieważ wyobrażam sobie, że klient pokazujący album może być zainteresowany, wymieniając utwory według tytułu, ale także pokazując długość każdego utworu - większość klientów tak robi. Z drugiej strony nie mogę pokazać kompozytora (ów) ani artysty (artystów) dla każdego utworu, ponieważ uważam, że na tym poziomie informacje te nie są konieczne. Oczywiście twoje wybory mogą być inne.
GET /tracks/:trackId
zwraca informacje o określonej ścieżce. Ponieważ nie ma już hierarchii, nie musisz zgadywać albumu ani wykonawcy: jedyne, co naprawdę musisz wiedzieć, to identyfikator samego utworu.
A może nawet nie? Co jeśli możesz podać to po nazwie za pomocą 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
}
}
Teraz spójrz bliżej albums
; co widzisz? Racja, nie jeden, ale dwa albumy. Jeśli masz hierarchię, nie możesz tego zrobić (chyba że powielisz rekord).
GET /comments/:objectGid
. Być może zauważyłeś brzydkie identyfikatory GUID w odpowiedziach. Te identyfikatory GUID umożliwiają identyfikację jednostki w bazie danych w celu wykonania zadań, które można zastosować do albumów, wykonawców lub utworów. Takie jak komentowanie.
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"
}
]
Komentarz odwołuje się do danego obiektu, umożliwiając przejście do niego podczas uzyskiwania dostępu do komentarza poza jego kontekstem (na przykład podczas moderowania najnowszych komentarzy przez GET /comments/latest
).
Pamiętaj, że nie oznacza to, że powinieneś unikać jakiejkolwiek formy hierarchii w interfejsie API. Są przypadki, w których ma to sens. Jako zasada:
Jeśli zasób nie ma sensu poza kontekstem zasobu nadrzędnego, użyj hierarchii.
Jeśli zasób może żyć (1) sam lub (2) w kontekście zasobów nadrzędnych różnych typów lub (3) ma wielu rodziców, hierarchia nie powinna być używana.
Na przykład linie pliku nie mają sensu poza kontekstem pliku, więc:
GET /file/:fileId
i:
GET /file/:fileId/line/:lineIndex
są w porządku.
SongSearchResult
zakładam, że jest w porządku. Ale co jest z adresami URL? Czy powinienem podaćparentID
każdy obiekt i użyć go jako parametru GET lub zwykłej części adresu URL? Co jeśli mam głębokość> 2?/artist/1/album/10/song/3/comment/23
- szaleństwem jest podawanie każdego identyfikatora artysty, albumu i piosenki wcomment
obiekcie, ale słyszałem, że jest to dobra droga, ale czyż nie jest dsigusting ?!