Куди нам слід поставити пошукову дію?
В GET /search/:text
. Це поверне масив JSON, що містить відповідність, кожен матч, що містить альбом, до якого він належить. Це має сенс, тому що клієнта може зацікавити не сам трек, а весь альбом (уявіть, що ви шукаєте пісню, яка, ви вважаєте, була в тому самому альбомі, як і назва, яку ви пам’ятаєте).
буде не так добре повертати батьківські ідентифікатори з кожним так. Я помиляюся?
Окремі композиції можуть містити альбом. Це забезпечить рівномірність представлення доріжок, якщо ви можете отримати трек або через альбом, або через пошук (тут немає альбому).
Який краще?
Як було сказано раніше, в тому числі альбом має сенс. Хоча третій пункт (з відносним URI) може бути цікавим у деяких випадках (не потрібно думати про те, як повинен бути сформований URI), він має недолік, якщо явно не надавати альбом. Четвертий пункт це виправляє. Якщо ви бачите перевагу наявності відносного URI у відповіді, ви можете комбінувати точки 3 та 4.
А може, я німий?
Вибір хороших URI не є легким завданням, тим більше, що немає єдиної правильної відповіді. Якщо ви розробляєте клієнта одночасно з API, це може допомогти вам краще уявити, як API може бути використаний. З цього приводу, інші люди можуть віддавати перевагу іншим звичаям, про які ви не думали, розробляючи API.
Аспект, який може бути проблематичним, - це організація внутрішньої організації даних, тобто використання ієрархії. З вашого коментаря вам цікаво, що має містити відповідь на це GET /artist/1/album/10/song/3/comment/23
, що показує дуже орієнтоване на дерево бачення. Це може призвести до виникнення кількох проблем при продовженні системи згодом. Наприклад:
- Що робити, якщо у пісні немає альбому?
- Що робити, якщо в альбомі є кілька виконавців?
- Що робити, якщо ви хочете додати функцію, яка дає можливість коментувати альбоми?
- Що робити, якщо слід залишити коментарі?
- тощо.
Це, по суті, проблема, яку я пояснив у своєму блозі : представлення дерева має занадто багато обмежень, щоб ефективно використовуватись у багатьох випадках.
Що станеться, якщо зруйнувати ієрархію? Подивимось.
GET /albums/:albumId
повертає JSON, що містить мета-інформацію про альбом (наприклад, рік, коли він був опублікований або URI JPEG, що показує обкладинку альбому) та масив треків. Наприклад:
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"
}
...
]
}
Чому я включаю, наприклад, довжину кожного треку? Тому що я думаю, що клієнту, який демонструє альбом, може бути цікаво, перераховуючи доріжки за назвою, а також показуючи довжину кожного треку - більшість клієнтів це робить. З іншого боку, я не можу показувати композитору чи виконавцю для кожної композиції, тому що я вирішую, що ця інформація на цьому рівні не потрібна. Очевидно, ваш вибір може бути різним.
GET /tracks/:trackId
повертає інформацію про певний трек. Оскільки вже немає ієрархії, вам не потрібно вгадувати альбом чи виконавця: єдине, що ви дійсно повинні знати, - це ідентифікатор самого треку.
А може навіть і ні? Що робити, якщо ви можете вказати його по імені 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
}
}
Тепер придивіться уважніше albums
; що ти бачиш? Правильно, не один, а два альбоми. Якщо у вас є ієрархія, ви не можете цього робити (якщо ви не дублюєте запис).
GET /comments/:objectGid
. Можливо, у відповідях ви помітили некрасиві GUID. Ці GUID дозволяють ідентифікувати об'єкт у всій базі даних, щоб виконувати завдання, які можна застосувати до альбомів, виконавців або композицій. Такі як коментування.
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"
}
]
У коментарі йдеться про відповідний об’єкт, що дозволяє перейти до нього під час доступу до коментаря поза його контекстом (наприклад, при модеруванні останніх коментарів через GET /comments/latest
).
Зауважте, що це не означає, що вам слід уникати будь-якої форми ієрархії у вашому API. Бувають випадки, коли це має сенс. Як правило:
Якщо ресурс не має сенсу поза контекстом його батьківського ресурсу, використовуйте ієрархію.
Якщо ресурс може жити (1) поодинці або (2) в контексті батьківських ресурсів різних типів або (3) мати декількох батьків, ієрархія не повинна використовуватися.
Наприклад, рядки файлу не мають сенсу поза контекстом файлу, тому:
GET /file/:fileId
і:
GET /file/:fileId/line/:lineIndex
добре.
SongSearchResult
це добре, я припускаю. Але що стосується URL-адрес? Чи потрібно надаватиparentID
кожен об'єкт і використовувати його як параметр GET або нормальну частину URL-адреси? Що робити, якщо у мене глибина> 2?/artist/1/album/10/song/3/comment/23
- божевільно надавати кожен ідентифікатор виконавця, альбом та пісню вcomment
об’єкті, але я чув, що це шлях, але це не гасне ?!