Галоўная / Артыкулы

Частыя памылкі у даговоре API, якія пашкоджаюць надзеямасць фронтэнда.

Дзесять распашытых памылак у кантракта API, які парадуруюць надзеямоасобу, — ад зміны формату адпаведзей і коду 200 OK за кожную памылку да нестабільнай структуры сторінавання, з способамі выправлення.

Выдавец: REACTAPP.TOP18 хв чытання4119 слоў

Крыніцы: 10 API Design Mistakes That Make Frontend Developers Hate You

API можа выглядаць бездыяковай на паперы, але працаваць так, што всі, хто на яе будуе, страждаюць.

Тэрмін адпаведзення вяртае правільны JSON. Код статусу супараднаў. Адпаведзенне прыходзіць быстра. З точкі зору бэкенду, задача выглядае завершанай. Але інжынеры фронтэнду бачаць зусім іншае. Кожны вызов выклікае неабходнасць дапамогі дадатковых захоўніх пераканаў. Тэрміны адпаведзення, якія выглядаюць падобна, вяртаюць абсалютна разныя даны. Паведамленні пра аблекты чытаюцца як лініі журнала, а не так, як іх мяжваў бачыць корыстнік. Функцыя стораначэння працуе нестабільна для разных ресурсаў. Не існуе надзеянага спосабу адзначыць пустую значэнне ад таго, якое не існуе, чы роўна ад невялікай запросу.

Няхайшая з гэтых прыткосцей не выходзіць ад таго, што разработчыкі фронтэнда чакаюць, што бэкэнд будзе прыстосаваць кожны адказ да конкрэтнага компонента. Якша спроектаваны API не павінен відпаваць ніякаму конкрэтнаму інтерфейсу. Ёму патрабуецца достатнія яснасць, каб многа розныя інтерфейсы маглі ствараць прыкладнае паведамленне ў зв’язку з ям.

Моцныя контракты API скарочуюць колькасць здогадак. Яны чытальна пазначаюць, што ўспело, што не успело, якія поля є необавязковымі, як сортуюцца рэзультаты, чыісць дадзеныях старонак, і якія значэнні можна безбедна кэшаваць або поручваць з часам. Слабыя контракты перадаюць усю гэтую неяснасць на іншыя стороны, змушаючы кожны веб-сайт, мобільны дапрыяг, панель адміністрацыі і інтэграцію з трэцімі сторонамі самостайна выдумваць сваю інтерпрэтацию.

Самэй тады пачынаецца незадоволенне. Фронтэнд перестае спрыягаць з API як з джэрелам правды і пачынае спрыягаць з ям як з чымось, што трэба пасправляць.

1. Верненне разныя формы адпаведзібы з кожнага эндпункта

Адзін эндпункт вяртае простае масавэ. Іншы размешчае свой палладоў унутрь ключа data. Трэці выкарыстоўвае поля result, message і success. Маршрут з пагінацыяю храніць свае записы пад ключам items, тады як суседзіцькі маршрут называе тое ж самае rows. Якщо выдаліць об’ект через аднаго кантролера, вы отрымаете выдаленую запись; якщо через іншага — нічога.

Якщо розглядаць кожны з іх окрема, ніякая з гэтых адпаведзіб не ўскладненая для разумення. Проблемы выйшаюць, калі команда фронтэнду прабуе стварыць спільную, можна-паўтарна выкарыстоўваную логіку для взаімадзеяння з API як цэлым.

Немагчыма з абсалютной вярнасцю напісаць елемент-памочнік для запыткаў, механізм карання памылак чы адаптэр для сторнікацыі, таму што кожны канцэнтрабынт вымагае свайго сабскіпу. Компаненты вынужданы працаваць з неадрэсна глыбокімі, неканцэнтрычнымі структурамі, толькі каб выявіць патрэбную значэння:

const users = response.data.result.users;
const orders = response.items;
const reports = response.data.rows;

Відчутныя наследкі — це дублірацыя коду для карэткавання. Глыбокіяя наследкі — це неперакладнасць. Калі разработчык фронтэнду стаўкаецца на канцэнтрабынт, з якім раней не працаваў, у ёнага немае можлівасці здогадацца пра яго структуру на адлік ведамасцяў пра роботу рэшты API.

Канцэнтрычнасць не значыць, што кожны адпаведзень павінен мець ідэнтычныя поля. Одна рэсурс, спіс рэсурсаў, рэзультат пасля сторнікацыі, вынік каманды і асінхронная задача — усе гэта означае разныя речы, і цілком логічна, што ўсе яны маюць разную структуру. Галоўнае — кожная з гэтых категорыяў павінна мець такую структуру, якую фронтэнд можа адразу распазнаць.

Рэспанс зі спісам можа завжды практычна апавярнюваць свае записы разам з дзеяным метаданаямі. Каманда завжды можа вернуць або апцэнаваны ресурс, або чыткая апрацаваная аб’ект рэзультата. Адказы за апбоўкі завжды можа выглядаць за аднаковай структурой. Станы пустоты можна представіць аднойчыны ў всіх падобных канцах.

Адносны дизайн рэспанса дапамагае заліць інфраструктуру фронтэнду простай. Неадносны дизайн ператварае кожны экран у індывідуальны адаптар, налаштаваны па таму, калі саме разработчык бэкенду напісаў той чырвоны маршрут.

2. Іспытанне 200 OK для кожнага рэзультата

Дзеяныя API адпавядаюць з 200 OK незалежна ад таго, што на самай працэ выйшло, хаваючы рэальны рэзультат у тэле рэспанса:

{
  "success": false,
  "message": "User not found"
}

Этый шаблон зазвычай выклікаецца як спрощэнне для адрабатавання запыткаў з баку кліента: кожны запыт рашаецца адносова таму, што фронтэнд проста перакантрацеўваеся на значэнне флага success у тэле запытка.

У практыцы гэта пазбавляе значэння таго, што ўжо безкоштовна надавалася слоем транспортування.

Кліенты HTTP, інструменты монітарынгу, кэшы, проксі, API браузераў і бібліятэкі для запошуку дадзеных — усе яны практыкуюцца на адной з катэгорыяў кода стану. Запыт, які быў адхілены, можа сама сабою перайсці ў стан адказу пра аблыканне. Успешнае стварэнне можа быць адразліваецца ад звычайнага чытання. Конфлікты можна адрабатваць інакш, чым невалідныя даны або відсутні токены автанацыі.

Калі кожны адказ вяртаецца як 200, фронтэнду неабходна памяць пераглядаць тэла кожнага запыту. Якщо забыць пра гэта, аперация, якая не выйшла, можа здавацца успешной. Звычная логіка прабоўкі стае рызыкавай, таму што кліент больш не можа адразніць тымчасовую памяшчанне сервера ад бяглынкі верыфікацыі. Спрабаўнасць таксама падвергаецца негатыўнам наследкам, калі панелі керування адзвярцаюцься пра хвілю успешных запытоў, тады калі ў рэальнасці корыстувачы сталкнуліся з аперациямі, якія не выйшлі.

Адваротныя помылкі — гэта аб’еднаванне всіх аперацияў, якія не выйшлі, ў 500. Відсутнае запіс, некоректны запыт, проблемы з правамі, дуплікатныя значэння і перыводныя аператыўныя памяшчанні — гэта не адна і тая ж категорыя аперацияў, якія не выйшлі. Аб’еднаванне ўсіх іх у адну звычную памяшчанне сервера вымагае ад фронтэнда параскладваць тэкст паведамлення, каб з’ясаваць, што на самай працоўцы паспела памяшчанне.

Коды статусу ніколі не былі прызначаны для таго, каб неслі весь бізнес-значэння адпаведнай адпаведзі, але яны павинны точна класыфікаваць рэзультат. Тады тэла адпаведзі можа несць усія структураваныя деталі, якія на самай працэ інтэрфейсу патрабуюцца.

Фронтэнд не павінен працаваць над распакоўкай фразы "электронная пашта вялікай часткай існуе" толькі каб з’ясавіць, што ўстаўае конфлікт.

3. Адправка тэксту аб бядах без жадной структуры

Простая паведамленне аб бядах можа быць дастатнім для таго, хто чытае лог-файлы, але яна рэдка калі дае інтэрфейсу достатнькі матэрыял для працы.

Уявіце сабе, што канцэнтр падпісу на адпаведзь дае ўтварэнне на кшталт:

{
  "message": "Validation failed"
}

З гэтага кліент не мае можлівасці з’ясавіць, якое поле спрычыніла проблему, якая правіла была наражана, чы не калькі палейзаў зазналі нядачы адразу, чы ўзагалі гэтая беда стосуецца формы.

У такій ситуацыі разработчыкі вынужданы пісаць нестабільную логіку падбору строк: якщо у тексте згадваецца „электронная пашта“, то адпаведныя праблемы прыкладзяюцца да поля для введэння пашты; якщо згадваецца „пароль“, то паказуецца адпаведны застерэжэння. Як толькі серверная частка змянюе формулювання, выправляе опечатку, змінюе регистр або дадае локалізацыю, гэтая логіка тыхо перестае працаваць.

Кращы падход — аддзеліць тое, што машына павінна зрозумець, ад таго, што чалавек павінен прачытаць. Адпаведны адказ можа включаць стабільны код праблемы, деталі па кожнаму полю і інфармацыю пра запит, а таксама паведамленне, якое можна без проблем адобразіць або запісаць.

Калі такая структура ўжо існуе, фронтэнд можа сам адначыць, як кожная памылка должна выглядаць на экране. Неспраўныя перакананні на рэвэлі поля можна прадстаўляць пры самым вводзе. Неспраўнасць у автарызацыі можа спрычыніць перенаправленне або схованне недзейнае дзеяння. Памылка, вызваная канфліктам, можа запропанаваць корыстніку спосаб её рашэння. Тымчасовая неспраўнасць службы можа захаваць тое, што корыстнік пісаў, і запропанаваць кнопку перапрыбутку замест таго, каб стерць яго работу.

Нічыга з гэтага не значыць неабходнасці включэння неапранутых трэсаў выключэнняў аб рэчыцах памылак базы дадзеных у адпаведны рэспонс — гэтыя элементы часта адкрываюць внутранізныя деталі рэалізацыі і ў будзь-якім случае ствараюць плутанне. Задачай бэкэнду є перакладаць нізкія неспраўнасці на стабільныя, чыста апісаныя памылкі домэна.

Якша адзячынаная пакет-інфармацыя пра адзіёмкі дазволяе кліенту адпаведаць на тры базовыя запытанні: якая категорыя адзіёмкі, да какой часткі інтэрфейса яна належыць, і чыму ў корыстніка є можлівасць якісь дзеяння ў зв’язку з яю.

Якщо не выкарыстоўваць такую структуру, кожны фронтэнд, які ўжоў яе, вынужаны будзе сам ствараць сабе неясную інтэрпретацыю таго, што вернуў бэкэнд.

4. Адносаванне null, відсутных поль, порожніх строек і порожніх масів як взаімна заменяемых элементаў

Кожны необавязковы элемент у API патрабуе чыстаўкавага значэння для яго відсутнасці.

Поле, якое не прысутнае ў пэйлоадзе, можа значыць, што яго проста не было запрошана. Значэнне null можа значыць, што система чытвацки ведае, што там нічога няма. Пустая строчка можа значыць, што корыстнік выбраў не вводзіць тэкст, а можа быть проста симптамам старэйшаг коду, які паслаба адносіцца да відсутных значэнняў. Пустыя масавыя элементы можа значыць, што сапраўды няма жадных адносоўных элементаў, а можа значыць, што аднос не быў завантажаны і тыха заменены на пусты список.

Калі API сумешчае гэтыя форматы без аднаковасці, фронтэнд не мае надзейны спосабу дазнацца, з якой саме ситуацыяй ён насправдзе мае супакоўка.

Поле прафіля можа быць зовсім не падаць у аднай адпаведзі і з’явіцца як null у іншай. Канець-точка для спісу можа вернуць null заместо порожняй масы, калі няма чаго паказваць, што значыць, кожны компонент должен пераканальваць данні раней, чым можа яны ўжо выкорыстовваць іх. Дата, якая недоступна, можа паказвацца як порожняя строка, што тады наражае бібліятэкі для парсінгу, якія чакаюць правільны формат. Связь, якая не змогла быць завантажана, можа буць тыхо адобразаваная як порожняя маса, чым справжнія адказка выглядае точна як законны стан порожнечы.

Прыродны рэзультат — код фронтэнду, заполнены захоўнай нормалізацыяй, у дусе:

const records = Array.isArray(response.records)
  ? response.records
  : [];

const displayName =
  response.displayName ?? response.name ?? "";

Адэкватная ступень нормалізацыі ўсё ж разумна — зовнішнія системы за сваёй прыродай є ненадзеянымі, і кліенты должны захіщацца ад гэтаго. Проблема выявляецца тады, калі фронтэнд больш не справляецца з практычнымі ненадзеяносцямі зовнішніх систем, а ўзамен прыкрывае недастаткі у контракце API, який не можа чытлаўна визначыць, што означае «нічога».

Рашэнняякое — каб API намеравана визначыў, што саме представляе кожны вид абсэнцыі. Колекцыі должны застаўаться колекцыямі нават тады, калі ў іх нічога няма, а не ператварацца ў null. Поле, якія можна легітымна залишыць порожнімі, должны быць дозволеныя да пустых значэнняў намеравана, а не випадкова. А калі якое-небудзь поле зовсім не прадстаўляецца, для гэтага должна існаваць задокументаваная прычына — напрыклад, рэдкае наявнасць поль, обмежэння прав або спецыфічныя параметры канцаўкі.

Калі абсэнцыя мае стабільны значэнне, станы інтэрфейсу стаюць более чыстасправнымі. Фронтэнд можа розразліцаваць межу „немае каментароў“, „каментары не былі включаныя ў гэты адказ“ і „каментары не падаюць“.

Это тры абсалютна разныя досвядчэння корыстувальца, хоць усе тры на першы погляд можу выглядаць ідэнтyczна: порожняя частка для каментароў, дзе нічога не паказваецца.

5. Адкрыцья неапранутых модэляў базы дадзеных працоўна через API

Серыялізацыя аб’екта ORM безпосередна і ўсыланне яго як адказа можа здавацца найпростым спосабам — аб’ект вже знаходзіцца ў памяці, тады чаму пісаць яшчо адны шар толькі каб перакаштаваць яго?

Проблема ў тым, што рэдкі базы дадзеных і контракт API існуюць з разных прычын.

Тэбл можа мець внутрашнія коды статусу, столбцы з іншымым ключам, часовыя пазначкі для «мягкага» выдалення, метаданы аудыту, шляхі до зберагача дадзейнаў або столбцы, якія засталіся пасля пакульнай міграцыі. Прямая серыялізацыя такой структуры прыўязывае кожнаго кліента да выбораў па зберагачэнню дадзейнаў, пра якія ёму ніколі не трэба было ведаць.

Калі фронтэнд начынае выкарыстоўваць такія поля, як user_role_id, deleted_at або структуру вялізаных звязкаў, якая проста ёсць наследкам адпаведнай настройкі ORM, бэкенд застрягае. Пазнейшая змена назвы столбца, раздзеленне тэблы, змена спосабу аўтаматычнага завантажэння дадзейнаў або міграцыя на іншую службу — усе гэта, што мяло бы застацца чыста внутршнімі перэрабкамі, раптам стае прычынай бяспекавых змян у публічным API.

Прымэчанне энтытаў безпосередна таксама стварае рызык нехтаўнага адкрыцья інфармацыі. Хтось дадае новую столбец у базе даных, і чынючы, што стандартны серыязавальнік уключае ўсе поля, яны праказуюцца ў адпаведзях API без таго, каб хтось прыняў рашэнне пра ўключэнне іх. Внутршнія зьместы, чулыя метаданы або значэньні, важныя для безпекі, могу выцэклаць такім чынам без жадных намераваных рашэньняў у дызайне.

Спецыяльны модэль адпаведзі разв’язвае гэтыя проблемы, выступаючы як межа. Ён чытка паказывае, на якія поля кліенты могу рэгламентавацца, перакладае представленні на рэвэле хранення ў значымыя концэпты домэна, і запобегае нехтаўнаму прасачанню внутршняй структуры ў публічны кантракт.

Для гэтага не трэба рукамі пісаць вялічезную функцыю каратэрызаціі для кожнага оканчальнага пункта. Серыялізаторы, якія працуюць за дапамою схемы, і утиліты каратэрызаціі, якія можна викорыстоўваць знову, могу значна зменшыць колькасць павтарэнняў. Галоўнае — форма адпаведзі ёсць свядомы выбар, а не пасляэфект таго, што вярнуе ORM.

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

6. Стварэнне пагінацыі, на якую няма чаго рацыянацься

Пагінацыя здаецца простай, пакуль базовыя даны не змінююцца, калі хтось яшчэ праскролвае іх.

Канцэнтрапт прымае page і limit, застаўляе афсэт і вяртае частку звістак. Фронтэнд адрасавае кантролы сторунак і праходзіць праз спіс. Всё гэта працуе чыста, пакуль не будуць дадзеныя новыя рядкі, старыя рядкі не будуць выдаленыя або порядак сортавання не будзе фіксаваны.

Уявіце, што корыстнік адглядае першую сторунаку. У тым часе новая звістка дадаецца поблізу верхней часткі калекцыі. Калі гэты корыстнік запитае другую сторунаку, элемент, які ён вялікі час адглядаў на першай сторунаку, з’явіцца знову, таму што афсэт змяніўся. У іншым месцы іншая звістка можа быць абсалютна прынятая і ніколи не паказана.

Ситуацыя становіцца ўжо горшай, калі сама точка выходу з самага пачатку не гарантуе стабільнага порядку. Тады дваржовая сістэма можа вяртаць рядкі ў будзь-яму порядку, які паспадабляецца ў планавальніку запытоў. Два ідэентычныя запыты, аднаго за другім, можу вяртаць рядкі ў разным порядку, нават якщо нічага значэннявога ў дадзенах не змянілася.

Гэта не тое, што фронтэнд можа выправіць сам. Усё залежыць або тым, чы рэндзер бэкэнда будзе забезпечваць детерміністычны порядак разам з метаданаямі пагінацыі, якія дзейсна маюць значэнне.

Пагінацыя на адказе, яка ўжоўваецца разам з гарантаваным порядкам сортавання, добра працуе для большай часткі набораў дадзеных. Але для кантэнта, які часта зміняецца, або для вельмі большых колекцыяў, пагінацыя на курсары зазвычай лепша вытрымае такія змены. Выбор падходу залежыць ад продукту, але незалежна ад таго, кой выбераш, у дакументацыі павінна быць чытка адзначена, як кліент пераходзіць між элементамі колекцыі.

У адказе па пагінацыі таксама павінны быць даны кліенту адказы на дзеякі практычныя запитанні. Чы є наступная сторонка? Какое значэння курсара павінен выкорыстоўваць наступны запит? Чы є загальная колькасць точной, це толькі адказ на запит, чы проста яе навмесна не падаюць? Што будзе, як сторонка, яку кліент зараз пераглядае, стане порожней чераз выдаленне елементаў?

Калі канцэнтрабынт вяртае записы без надзейных способаў для іх пераскоку, фронтэнд вынужаны ўтвараць кантроллы пагінацыі, якім ён не можа абсалютна даверыць. Карыстальнікі бачаюць дуплікаты і відсутныя елементы, а за проблемы, якія на самай справе ёсць праблемамі кантракту, вінаватыя стаюць інтерфейсы.

7. Адправка дат без паказання часовага поясу

Дата практычна ніколи не ёсць простаю стрэлкай.

Часовая пазначка без паказання часовага поясу можа абначаць местны час сервера, час зберагання ў базе дадзеных, савой местны час канечнага карыстальніка або значэнне, якое мяркувалася як UTC, але якое пазбавілася свайго зсуву ў якомусь моманце форматавання. Фронтэнд тады вынужаны адображаць, поручваць, сортаваць і запускать дзеяння на адной чыстаю значэннем, значэнне якога насправды задана толькі частка.

Возьмімо такой атрыбут, як "2026-08-04 09:00:00". У яго няма жадных пазнакаў, да канкрэтнага момента часу ён аднасецца. Сесія браузера ў Пакістане і сесія ў Канадзе могу розумець гэты стрынг по-разна, а змены часовых поясаў толькі падвайнаюць неяснасць.

Як загальная правіло, абсалютныя часовы пазнаки должны мець явны фіксаваны зсув або быть выражаныя у стандартным формате UTC. Календарныя значэння, якія не прыязначаны канкрэтнаму моменту, такія як дата нараджэння або дата вырачунку, должны застацца простымі значэннямі дат і не должны таямна зменшвацца або збільшвацца ў залежнасці ад часовых поясаў.

Гэтыя разлікі маюць рэальныя наследкі. Якщо пераканваты дату нараджэння, якая зберагаецца як паўначы ў UTC, у местны час, дзеякі корыстувальнікі пабачаць некаторы дзень раней. Навпакі, якщо спланаваны заход рассматрываць як простую строчку з датай, то всі пабачаць, як ён адбываецца за местным часам, а не у аднаковы момент для всіх.

API таксама павінен быць адносны ў точнасці та формате, якія ён викорыстоўвае на всіх канцэнтрах. Проблема вылучаецца, калі адной канцэнтры вяртае секунды Unix, іншай — мілісекунды, а трэцяй — які-небудзь спецыяльны формат строчкі.

Разработчыкі фронтэнду можаць форматаваць дату так, каб яна паспадзяралася локалізацыі корыстувальніка. Але яны не можаць воссоздаць часовую зону, пра якую API спачатку нічога не сказаў.

Проблемы, які стосуюцяся часовых поясаў, ёшчэ болей раздражаюць, таму што зазвычай усе працюе нормальна для команды, яка працуе у своем часовом поясе, а выходзіць з ладу толькі для корыстнікаў, які знаходзяцца в іншым месцы.

8. Прыведэнне простых экранаў да збору дадзеных праз ланцюг запытоў

Староніца запрашае дакупленае вярсці корыстніка. Калі корыстнік вяртаецца, староніца запрашае інфармацыю пра арганізацыю гэтага корыстніка. Калі інфармацыя пра арганізацыю надходзіць, староніца запрашае правы прыступ. Калі правы прыступ ўжо є, староніца нарэшце запрашае тыя записы, якія корыстніку фактычна разрэшаны бачыць.

Хоця кожны окремы канец-пункт адпавідае быстра, сам экран можа знадобіцца калькі секунд, прычаму ён пакажае ўжо якісь корыстныя данні.

Такі патэрны частаюць тады, калі API ствараецца выключна на адпаведных рэсурсах бэкенда, не врачуя таго, як кліент на практыцы чытае гэтыя данні. Дизайн сэрвера выглядае чыстым і апранутым, тады як кліенту даваецца задача організаваць цэлы последовны процес, толькі каб атрыбуаваць адну сторанку.

Разработчыкі фронтэнда рэагуюць на гэта, вкладваючы станы завантажэння ў іншыя станы завантажэння. Працоўныя недачы на яком-небудзь этапе можу заставіць экран застацца часткова ініцыялізаваным. Керуванне абраннем стае складным, калі корыстнік пакідае сторанку пад час завантажэння. А тыя ж самыя базовыя данні часта запрашваюцца колькаразо, таму што кількі компонентаў кожны незалежна маюць свой лінк у гэтым ланцугу.

Рашэнь не ў тым, каб вываліць усю базу дадзеных з аднаго вялікага канцэнтрабы. У замен, бэкэнд должен распазнаць важлівыя шляхі дзеяння кліента і адкрыць моделі для чытання, створаныя для ўстойчывага адпаведнага обслужвання.

Напрыклад, канцэнтраба панелі керування можа адразу вернуць падсумковыя даны і флагі можлівасцей, якія ёй патрабуюцца. Канцэнтраба дакладнаў записа може аб’еднаваць маленькія супакойныя об’екты, якія завжды неабходны для адзору. Калі часткі дадзеных справжна незалежныя адзінама ад другых, паралельныя запиты таксама ўважаюцца розумным варыянтом.

Запиты у формате графа, шары бэкэнд-за-фронтэнд, параметры расширэння рысоў і спецыяльна створаныя канцэнтрабы — усе гэта ўпрыемныя засобы для гэтага. Конкретны архітектурны стыль мае меншое значэнне, чым рэзултат: звычайныя экраны не должны прымушваць браузер поступова адкрываць граф зв’язкаў бэкэнду па адны запит за раз.

API не здобывае вышэйшых балаванаў за дизайн толькі таму, што кожны канцэнтры паўнасправна адпавядае адной табелі базы дадзеных. Якісна спроектаваная угода таксама должна врачываць, як фактычна выкарыстоўваныя даныя на другай стороне.

9. Скрытыя бізнес-правілы за «зеленым святлам»

Іноды канцэнтры для мутацый адзвяртаеся пра успех, нават якщо падстаўны рэзультат ўсё яшчэ не досягнуты.

Запрос на стварэнне звіту падае ў чергу на адработку у фонавым режыме. Аплата пераходзіць у статус «у ачакванні». Операцыя выдалення запланавана на выконанне пасля певнага періяда зберагачэння. Прадастальнік трэцьяй стороны падтверджае, што он прымёў запрос, але не тое, што завершыў роботу.

Калі API адпавядае тым самым пакетам дадзеных пра успех, які ён выкарыстоўвае для справжна завершанай роботы, фронтэнд рызыкуе паведаміць корыстувальніку інфармацыю, якая ўсё яшчэ не є правдой.

Інтерфейс можа практыкаваць адказ «Звіт гатовы», калі ўсё яшчэ перад тым, як ён будуе створаны. Ён можа адмахнуць рэяд зі спісу, нават якщо сервер толькі пазначыў яго для будучага выдалення. Ён можа паказваць платеж як завершаны, калі прадаўцу ёшчэ можна адмовіць у яго пазней.

Кліентам патрэбны способы, каб розразняць операцыі, якія выпаны, прыняты, ўсё яшчэ у процесе, часткова успешныя або чакаюць дальнейшых дзеянняў. Гэта не проста дробны аспект реалізацыі — гэта безпасова вплывае на тое, што інтерфейс можа чыста і правдзіва падаць корыстніку.

Для аперацыяў, якія выконваюцца ў рэальны час, часта цяжкае ўскладніць іх у самостойны об’ект задачы з ID і полем статусу. Станы, якія знаходзяцца ў проміжных умовах, трэба чытальна паказваць, а не сумаваць іх у загальны статус „успех“. Калі рэзультат частковы, у адпаведзе ўскладніць точна паказаць, што было выканана і што — ні.

Тая ж дисцыпліна ўзмацнюе процес павторных спроб. Якщо запит заканчыўся таймаутам, але сервер можа вэські ўжо працаваць над яным, фронтэнд не должен проста падаць запит знову і спадзявацца. Наявнасць ID аперацыі чы ручкі ідэмпотентнасці дазволяе кліенту без абаранення павторна спробаваць чы пераканацца ў статусе, не рызыкуючы падвойнымі наследкамі.

Адпаведзе пра успех должна відбіваць тую рэальную гарантыю, якую сервер можа дастаць у даны момент — нічога больш.

Это справжняя прыгода для раздражэння, калі інжынерам фронтэнду даводзится самім выявляць, чы ранг 200 означае, што задача завершана, толькі пачалася, чы проста «нічога не вызвало кашы на пацеку».

10. Развітак перакантракту без плану для старых кліентав

Змяніць API здаецца простым, калі ствараецца толькі адна гілка фронтэнду, якая розвиваецца супрацоўна з яйным. Вы перэназываеце поле, налагоджуеце код кліента, выкладзеце ўсё разам і пераходзіце да наступнага крока.

У рэальных умовах так не працюе.

Калі-небудзь хтось можа залишыць старую вікно браузера ачытым пасля развяртання. Мобільны дапынг можа застацца встановленым на прыстрое месцы без апдэйта. Інтеграцыя з трэцімі сторонамі можа пачуць вашы змяны толькі за свайго раскладу выпуску. Стары кэшаваны пакет JS можа продовжваць запрашваць ваш новы бэкенд, які ўсё ще чакае старую форму адпаведзі.

Адзыяванне або перайменаванне поля можа таямніча зламаць код, які ніхто з команды бэкенду не можа зараз жа выправіць.

Дзеяныя з найбольшымі рызыкамі спачатку не выглядаюць такімі рызыкавымі. Замена значэння enum можа таямніча зламаць логіку умовай інтэрфейсу. Змена поля з неканцэльнае на канцэльнае можа паслабіць прынятыя заўважэнні, закладзеныя ў створаныя типы. Змена стандартнага порядку сортавання можа вывести пагінацыю з сінхрону. Адключэнне новага статусу адказу можа направіць запит па зэлыя іншы тракт адказу на кліенте.

Кантроль гэтага праблемы пачынаецца з разумення таго, хто на самай працоўвае з API. Внутршні кліенты, якія запускаюцца сінхронна з бэкендам, зазвычай можаць пераканацца на шырэйшыя ітераціі, чым інтеграціі, назначаныя для публікі — але нават чыста внутршняя системы выгадваюць ад паэтапных змян і поступовага завершання викорыстанні старых полей.

Практычныя тактыкі включаюць: адгукаванне новых полей перад зняць з выкарыстоўвання старыя, адстэйкаванне рэальных дадзеных пра выкарыстоўванне, каб знаты, калі можна без апасцярыба ўсё зняць, праходжэнне тэстаў кантрактаў з ключовымі корыстувальнікамі, а таксама вярнае версіюванне API, калі сэмантыка зменяецца настолькі фундаментальна, што немагчыма градуальна ўдосконаліць яе на месцы.

Нічга з гэтага не значыць, што кожны історычны кантракт павінен падтрымваліся вечна. Сэрца прыбліжэння — адмова дазволіць проблемам кліента стаць „проблемай каго-іншага з розгортанням“ толькі таму, што бэкенд быў выпускаем першым.

Калі іншыя системы стануць залежнымі ад API, яго працэздатнасць мае жыцёвы цикл, які праходзіць далей за код, який яго спачатку реалізаваў.

Дружэльнасць з фронтэндам не значыць дазволення фронтэнду кераваць API

Ояўна спроектаваны API — гэта не той, які проста відбівае тую форму, якая для конкрэтнага компонента React ёсць найзручнейшая для викорыстання. Гэта проста прыведзе да іншай, не менш кранглівай формы з’яўлення взаемазвязку.

У замен ён прысвячае стабільны значэння домэна, прыемлівую структуру, чыстае адчытнае выкладванне рэзультаатаў, а таксама достатню кантэкстную інфармацыю, каб кліенты моглі ствараць правильныя рашэнні без патрэбы ў здогадках. Ён чыста разлічвае відсутнасць дадзэнняў ад чыстага неякшання, роботу, якая ўсё ў процесе, ад роботы, якая вжо завершана, проблему верыфікаціі ад канфлікту, а таксама спосаб пераказу чаго-небудзь ад спосабу його зберагання.

Команды фронтэнду цалкам спрыяюць у рашыранні справжняй складнасці — пагінацыя, статусы адзінакоў, пераходы пад час завантажэння, асінхронныя процесы — усё гэта яны ствараюць рэгулярна. А тое, што насправды вывялівае людзей, — это случайная складнасць, якая выступае ў результате нэўпорядкованых форм адпаведзей і відсутнасці сэмантичных сигналоў, а не самай проблемы.

Найболей здаровыя адносіны межаў фронтэнду і бэкэнду ствараюць гэтыя контракты разам. Фронтэнд чытка адзначае, якія разлікі насправды вплываюць на поведэнне корыстувальца. Бэкэнд уточняе, якія гарантіі ён можа безпечна даваць і якія операцыі практычна розвіваюцца пра довшы час. Рэзультатныя умовы API не належаць цалкам ні однай з сторон.

API вызывае незадоволенне ў той момент, калі пачынае вывозіць свою супэнзію назаўнік.

Кожны неясны код статусу ператвараецца ў умовную галоўку на кліянцы. Кожны нэпасоўнае выкліканне адпаведзення ператвараецца ў іншую функцыю-адаптэра. Кожны неяўны структураваны код абрактара ператвараецца ў нестабільнае падборае цэха. Кожны нестабільны поле ператвараецца ў ўсё новыя захоўнікавыя перакананні на абсэнцыю значэння.

Нічга з гэтага не значыць, што добра апрацаваны API усуне весь работу фронтэнду.

Ён проста дбае пра тое, каб разработчыкі фронтэнду выдзейвалі свой час на рэальную ствароўку продукту, а не на постацейнае адгэнераванне таго, што хацела сказаць бэкэнд-сістэма.