Дизайн API в URL-адресах

Дизайн API | Horus267

Дизайн API: вибір між іменами і ідентифікаторами в URL-адресах.

Оригінал: Вівторок, 17 жовтня 2017 г.

Переклад: Ігор КОСОВИЧ

Якщо ви берете участь в розробці веб-API, ви знаєте, що є розбіжності з приводу підходу до стилю URL-адреси, який буде використовуватися в ваших API-інтерфейсах, і що обраний вами стиль має серйозні наслідки для зручності використання API і впливає на Дизайн API і його довговічність. Команда Apigee тут, в Google Cloud, багато роздумувала над дизайном API, працюючи як всередині компанії, так і з клієнтами, і я хочу поділитися з вами шаблонами дизайну URL, які ми використовуємо в наших найсвіжіших проектах, і чому.
Коли ви поглянете на відомі веб-інтерфейси, ви побачите кілька різних шаблонів URL.
Ось дві URL-адреси API, які ілюструють дві різні школи думки про URL:

  • https://ebank.com/accounts/a49a9762-3790-4b4f-adbf-4577a35b1df7
  • https://library.com/shelves/american-literature/books/moby-dick

Перша URL-адреса – це анонімна і спрощена версія реальної URL-адреси з американського банку, де у мене є поточний рахунок. Другий варіант адаптований з педагогічного прикладу в Керівництві по дизайну API для хмарної платформи Google.

Перший URL досить непрозорий. Ймовірно, ви можете здогадатися, що це URL-адреса банківського рахунку, але не набагато більше. Якщо ви не вмієте запам’ятовувати шістнадцяткові рядки, ви не зможете легко ввести цю URL-адресу. Більшість людей будуть покладатися на копіювання та вставку або на посилання для використання цієї URL-адреси. Якщо ваші шістнадцяткові навички обмежені, як у мене, ви не можете відразу зрозуміти, однакові або різні два однакових URL, або легко знайти кілька входжень однієї і тієї ж URL-адреси у файлі журналу.

Другий URL набагато прозоріше. Його легко запам’ятати, надрукувати і порівняти з іншими URL-адресами. У ньому розповідається невелика історія: є книга, яка має ім’я, яке знаходиться на полиці, яка також має ім’я. Цю URL-адресу можна легко перевести в пропозицію на природній мові.

Що ж ви повинні використовувати? Який Дизайн API обрати? На перший погляд може здатися очевидним, що URL #2 краще, але правда складніша.

Випадок для ідентифікаторів

Існує давня традиція – від попередніх комп’ютерів – призначення числових або буквено-цифрових ідентифікаторів для сутностей. Банки і страхові компанії виділяють ідентифікатори для облікових записів і політик. Виробники, оптовики і роздрібні продавці ідентифікують продукти з кодами продуктів. Видання книг ідентифікуються за номерами ISBN. Уряди випускають номера соціального страхування, номери водійських посвідчень, номери кримінальних справ, номери земельних ділянок та т. д. Наш перший приклад – просто вираз цієї ідеї в форматі URL-адреси всесвітньої павутини.

Якщо такі ідентифікатори мають недоліки, описані вище, важко прочитати, порівняти, запам’ятати і надрукувати і позбавити корисної інформації про об’єкт, який вони ідентифікують, – чому ми їх використовуємо?

Основна причина полягає в тому, що вони залишаються дійсними і недвозначними навіть тоді, коли ситуація змінюється, а стабільність і визначеність є критично важливими якостями (Тім Бернерс-Лі написав часто цитовану статтю по цій темі). Якщо ми не виділяємо ідентифікатор банківського рахунку, як ми можемо надійно посилатися на нього в майбутньому? Ідентифікація облікового запису з використанням інформації, яку ми знаємо про це, ненадійна, оскільки ця інформація може бути змінена і не може однозначно ідентифікувати обліковий запис. Детальна інформація про його власника може бути змінена (наприклад, ім’я, адреса, сімейний стан) або схильна до двозначності (дата і місце народження) або і те, і інше. Навіть якщо у нас є надійний ідентифікатор власника, право власності на обліковий запис може змінитися, а ідентифікація облікового запису, де і коли вона була створена, не гарантує унікальність.

Ієрархічні імена

Ієрархічне іменування – дуже потужний метод, який люди використовували протягом століть для організації інформації і розуміння світу. Систематики природи, розроблені в 1700-х роках Каролюсом ЛІннеєм, один дуже відомий приклад.

В основі цієї ідеї лежать URL-адреси в стилі другого прикладу, утворені з ієрархій простих імен. Дизайн API URL-адрес має зворотні якості простих числових, або буквено-цифрових ідентифікаторів: їх простіше використовувати, конструювати і отримувати інформацію, але вони нестабільні перед обличчям змін.

Якщо ви знаєте щось про таксономії Ліннея, ви знаєте, що його елементи були перейменовані, і ієрархія сильно змінилася з плином часу. Насправді темпи змін пришвидшились з впровадженням сучасних технологій, таких як аналіз ДНК. Можливість зміни дуже важлива для більшості схем іменування, і ви повинні відноситись з пересторогою до проектів які передбачають, що імена не зміняться. З нашого досвіду, перейменування і реорганізація ієрархії імен виявляються важливими або бажаними в більшості призначених для користувача сценаріїв, навіть якщо це не очікувалося оригінальними розробниками API.

Недоліком другого прикладу URL є те, що якщо книга, або полка змінює своє ім’я, посилання на неї на основі ієрархічних імен, подібних до цього в URL-адресі прикладу, будуть порушені. Зміна імені, ймовірно, не правдоподібне для книги, яка є копією друкованої літератури. Проте може застосовуватися до інших документів, які можуть наповнювати бібліотеку, і перейменування полки здається цілком правдоподібним. Точно так же, якщо книга переміщається між полицями, що також здається правдоподібним, посилання на цей URL також будуть порушені.

Тут є загальне правило. URL-адреси, засновані на непрозорих ідентифікаторів (іноді званих permalinks), по своїй суті є стабільними і надійними, але вони не дуже зручні для людей. Спосіб створення дружніх URL-адрес полягає в тому, щоб створювати їх з інформацією, яка має значення для імен та ієрархій, притаманних людям. В цьому випадку відбудеться одна з двох невдалих подій:

  • або ви повинні заборонити перейменування об’єктів і реорганізацію ієрархій,
  • або бути готовими впоратися з наслідками, коли посилання, засновані на цих URL-адресах, ламаються.

До цього моменту я говорив про наслідки цієї дилеми ідентичності з точки зору її впливу на URL-адреси, представлені API-інтерфейсами, але ця проблема також зачіпає ідентичності, що зберігаються в базах даних, і обмінюється між компонентами реалізації. URL-адреси, відкриті API, як правило, засновані на ідентифікаторах, які реалізує реалізація API в базах даних, тому проектні рішення, які впливають на URL-адреси, зазвичай також впливають на дизайн реалізації БД і API і навпаки. Якщо ви використовуєте ієрархічні імена для ідентифікації сутностей в реалізації, а також API, наслідки непрацюючих посилань поглиблюються, так само як і труднощі підтримки перейменування і репарації. Це означає, що ця тема дуже важлива для загального проектування системи, а не тільки для проектування API.

Краще з обох світів

Зіткнувшись з цими компромісами, який стиль URL ви повинні вибрати? Найкраща відповідь полягає не в тому, щоб вибрати: вам потрібно обрати як підтримувати повний спектр функцій. Надання обох типів URL-адрес дає вашому API стабільний ідентифікатор, а також простоту використання ієрархічних імен. В Google Cloud Platform  (GCP) сам API підтримує обидва типи URL для випадків, в яких перейменування або reparenting має сенс. Наприклад, проекти GCP мають як незмінну ідентифікацію, вбудовану в стабільні URL з постійною прив’язкою, так і окреме змінюване ім’я, яке ви можете використовувати в результатах пошуку. Ідентичність одного з моїх проектів GCP – «bionic-bison-166600» (який показує, що ідентифікатори не повинні бути такими незбагненними, як RFU-сумісні UUID – вони просто повинні бути стабільними і унікальними), і його ім’я в даний час “My First Project Renamed”.

Ідентифікатори призначені для пошуку. Імена для пошуку.

З принципів всесвітньої мережі ми знаємо, що кожна URL-адреса ідентифікує конкретний об’єкт. Цілком очевидно, що «https://ebank.com/accounts/a49a9762-3790-4b4f-adbf-4577a35b1df7» є URL-адресою певного банківського рахунку. Кожного разу, коли я використовую цей URL, зараз або в майбутньому, він завжди буде посилатися на один і той же банківський рахунок. Можливо, у вас виникне спокуса подумати, що «https://library.com/shelves/american-literature/books/moby-dick» – це URL певної книги. Якщо ви вважаєте, що перейменування і переміщення книг ніколи не буде мати сенсу в бібліотечному API, навіть гіпотетично, тоді ви, можливо, зможете захистити цю точку зору, але в іншому випадку ви повинні думати про цей URL по-різному. Коли я використовую цей URL-адресу сьогодні, це відноситься до конкретної й наявної копіїї Moby Dick, яка в даний час знаходиться на полиці американської літератури. Завтра, якщо книга, або полиця будуть переміщені або перейменовані, вона може відноситись до нової надрукованої копії, змінившої стару, або до будь-якої книзі взагалі. Це показує, що друга URL-адреса не є URL-адресою конкретної книги – це може бути URL-адресою чогось іншого. Ви завжди повинні пам’ятати про це і думати як про URL-адресу результату пошуку. Зокрема, результат цього пошуку:

знайти книгу, яка [в даний час] називається «moby-dick», і [в даний час] знаходиться на полиці, яка [в даний час] називається «американська література»,

Ось ще один URL-адресу для одного і того ж результату пошуку, де різниця повністю відноситься до типу URL, а не до значення:

https://library.com/search?kind=book&name=moby-dick&shelf=(name=american-literature).

Розуміння цих URL-адрес засновані на ієрархічних іменах, фактично представляють собою URL-адреси результатів пошуку, а не URL-адреси сутностей в цих результатах пошуку. Це є ключовою ідеєю, яка допомагає пояснити різницю між іменами і ідентифікацією.

Використання імен та ідентифікаторів разом

Щоб використовувати постійні посилання і URL-адреси пошуку, ви починаєте з виділення постійного посилання для кожного об’єкта. Наприклад, щоб створити новий банківський рахунок, я можу очікувати, що метод POST представить нові дані облікового запису на https://ebank.com/accounts. Успішна відповідь містить код стану 201 разом з заголовком HTTP «Місцезнаходження», значення якого є URL-адресою нового облікового запису: «https://ebank.com/accounts/a49a9762-3790-4b4f-adbf-4577a35b1df7».

Якби я розробляв API для бібліотеки, я б пішов по тій же схемі. Я міг би почати з створення полиці, відправивши наступний тег на https://library.com/locations:

{"kind": "Shelf",
 "name": "American-Literature",
}

Це призведе до розподілу наступного URL-адреси для полиці:

https://library.com/shelf/20211fcf-0116-4217-9816-be11a4954344

Потім, щоб створити запис для книги, я міг би відправити наступний текст в https://library.com/inventory:

{"kind": "Book",
 "name": "Moby-Dick",
 "location": "/shelf/20211fcf-0116-4217-9816-be11a4954344"
}

в результаті чого відбудеться виділення цієї URL-адреси для книги:

https://library.com/book/745ba01d-51a1-4615-9571-ee14d15bb4af

Ця стабільна URL-адреса завжди буде посилатися на цю конкретну копію Moby Dick, незалежно від того, як я називаю її, або де в бібліотеці я її поклав. Навіть якщо книга втрачена або знищена, ця URL-адреса буде продовжувати ідентифікувати її.

На основі цих об’єктів я також очікую, що такі URL-адреси пошуку будуть дійсними:

https://library.com/shelf/american-literatature/book/moby-dick
https://library.com/search?kind=book&name=moby-dick&shelf=(name=american-literatature)

Ви можете реалізувати обидва ці стилі пошуку в одному API, якщо у вас є час і енергія; в іншому випадку виберіть стиль для Дизайн API, якому ви віддаєте перевагу, і дотримуйтеся його.

Кожного разу, коли клієнт виконує GET по одній з цих URL-адрес пошуку, URL-адресу ідентифікації (тобто її постійне посилання, в цьому випадку https://library.com/book/745ba01d-51a1-4615-9571-ee14d15bb4af) знайденого об’єкта повинно бути включеним у відповідь. Або в заголовку (для цього є заголовок HTTP-вмісту Location), в тілі або, в ідеалі, в обох. Це дозволяє клієнтам вільно переміщатися між URL-адресами постійного посилання і пошуковими URL-адресами для тих же об’єктів.

Недолік двох наборів URL-адрес

У кожного проекту є свої недоліки. Очевидно, що для реалізації обох URL-адрес сутностей і URL-адрес пошуку в одному API потрібно трохи більше зусиль.

Більш серйозна проблема полягає в тому, що ви повинні навчати своїх користувачів того, який URL використовувати, в яких обставинах. Коли вони зберігають URL-адреси в базі даних або навіть створюють закладки, вони, ймовірно, захочуть використовувати URL-адреси ідентифікації (постійні посилання), навіть якщо вони можуть використовувати пошукові URL для інших цілей.

Ви також повинні бути обережні з тим, як ви зберігаєте свої ідентифікатори – ідентифікатори, які повинні постійно зберігатися при реалізації API, майже завжди є ідентифікаторами, які використовувалися для формування постійних посилань. Використання імен для подання посилань, або ідентифікаторів в базі даних рідко буває правильним – якщо ви бачите імена в базі даних, використані таким чином, ви повинні уважно вивчити ці використання.

Користувачі, які пишуть скрипти для доступу до API, можуть вибирати між URL пошуку і постійного посилання. Написання сценаріїв з пошуковими URL-адресами часто простіше і швидше. Ви можете легко створювати пошукові URL-адреси з імен або номерів, які ви вже знаєте, тоді як в скрипті зазвичай потрібно трохи більше зусиль для синтаксичного аналізу URL-адрес постійних посилань з заголовків і об’єктів відповіді API.

Недоліком використання URL-адрес пошуку в скриптах є те, що вони перериваються, якщо об’єкт API перейменовується, або переміщається в ієрархії. Так само, як скрипти мають тенденцію ламатися, коли файли перейменовуються, чи переміщуються. Оскільки ви звикли виправляти скрипти при зміні імен файлів, ви можете вирішити застосувати і використовувати URL-адреси пошуку і просто виправити скрипти при їх розриві. Однак, якщо для вас дуже важлива надійність і стабільність сценаріїв, напишіть свої сценарії за допомогою постійних посилань.

Постійне посилання і URL-адреси пошуку: краще разом

Якщо ви не дуже обмежуєте зміни, які ви дозволяєте своїм даним, ви дійсно не можете добитися стабільності, надійності і простоти використання в API з одним набором URL-адрес. Кращий Дизайн API реалізує обидва варіанти: URL-адресу з постійною прив’язкою на основі ідентифікаторів для стабільних ідентифікаційних і пошукову URL-адресу на основі імен (і, можливо, інших значень) для простоти використання. Для отримання додаткової інформації про Дизайн API читайте електронну книгу « Дизайн API: відсутня ланка » чи перегляньте ще декілька статей про дизайн API в блогу Apigee.

Перегляньте інші поради для Адміна 😉

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *