Надвор од алгоритмот: Архитектура за дизајн на API насочен кон човекот
Повеќето неуспеси кај API не се неуспеси на алгоритми. Тие се моменти на триење: клиентот не може да утврди кое поле е задолжително, пораката за грешка не нуди следен чекор, повтореното барање создава дупликат уплата или „мала“ промена во базата на податоци тивко нарушува мобилно издание што сè уште е во употреба.
Дизајнот на API насочен кон луѓето ги третира тие моменти како првокласни архитектонски прашања. Потрошувачот може да биде друг развивач, фронтенд-апликација, партнер за интеграција или услуга што ја одржува некој што не присуствувал на првичната дискусија за дизајнот. Во секој случај, API е интерфејс на производ. Неговиот квалитет не се мери само со пропусност и точност, туку и со тоа колку безбедно и самоуверено луѓето можат да го користат.
Започнете со задачата на корисникот, а не со листата на крајни точки
Каталогот на крајни точки може да изгледа уредно, а сепак да бара премногу работа од повикувачот. Дизајнирањето околу човечката намера значи да се започне со задачата: создавање нарачка, преглед на клиент, ажурирање на поставките за испорака или опоравување од неуспешно барање. Ресурсите и HTTP-методите остануваат вредни алатки, но треба да ѝ служат на задачата наместо да станат идеологија.
На пример, API за создавање нарачки треба да ги направи важните одлуки видливи. Повикувачот треба да знае кои вредности се прифатени, кои ги пресметува серверот, дали цените се меродавни и што се случува ако истото барање пристигне двапати. Криењето на овие одлуки зад нејасни имиња на полиња или имплицитни правила ја префрла сложеноста нанадвор, кон секој клиент.
Направете го договорот предвидлив
Доследноста е чин на емпатија. Користете ист стил на именување кај сите ресурси, претставувајте ги датумите во еден документиран формат и применувајте пагинација на ист начин каде и да се враќаат колекции. Клиентот не треба да мора да запомни дека една крајна точка користи page и per_page, додека друга користи offset и limit без јасна причина.
- Користете именки што одговараат на деловниот јазик кој корисниците веќе го разбираат.
- Враќајте стабилни идентификатори и разликувајте ги од ознаките за прикажување.
- Разликувајте отсутни вредности од празни вредности кога таа разлика е важна.
- Документирајте ги стандардните вредности, ограничувањата и несаканите ефекти покрај полињата што ги активираат.
- Одржувајте ги облиците на одговорите предвидливи, особено за грешки и пагинирани резултати.
Предвидливоста не значи ригиден минимализам. Одговорот може да содржи корисни врски, информации за статусот или метаподатоци за валидација кога тие детали му помагаат на повикувачот да ја заврши работата. Тестот е едноставен: дали оваа информација отстранува едно дополнително барање, претпоставка или разговор со поддршката?
Грешките треба да му помогнат некому да се опорави
HTTP-статусниот код е неопходен, но ретко е доволен. 422 му кажува на клиентот дека валидацијата не успеала; не кажува кој влез е невалиден, зошто е невалиден или дали повикувачот може да го исправи. Корисниот одговор за грешка зачувува машински читлив код, притоа нудејќи јасно и безбедно објаснување.
{
"error": {
"code": "validation_failed",
"message": "Барањето содржи невалидни полиња.",
"fields": {
"email": ["Внесете важечка адреса на е-пошта."],
"items.0.quantity": ["Количината мора да биде најмалку 1."]
}
}
}
Не изложувајте траги од стек, SQL-пораки или топологија на внатрешни услуги. Тие детали не се применливи за потрошувачот и можат да откријат информации за имплементацијата. Логирајте го дијагностичкиот контекст внатрешно, прикачете идентификатор на барањето во одговорот и дајте им на тимовите за поддршка сигурен начин да поврзат пријавен неуспех со докази од серверската страна.
Неуспесите исто така бараат намерна семантика. Неисправното барање не треба да изгледа како привремен прекин. Одговорот за ограничување на стапката треба да им каже на клиентите кога да се обидат повторно, ако API може да ја обезбеди таа информација. Истекот на времето мора внимателно да се разгледа: серверот можеби ја завршил операцијата иако повикувачот не го примил одговорот.
Дизајнирајте повторувања пред продукцијата да го наметне тоа
Мрежите откажуваат на начини што апликацискиот код не може целосно да ги контролира. Врските се затвораат, прокси-серверите истекуваат и клиентите се обидуваат повторно откако ќе изгубат одговор. За операции што создаваат или наплатуваат нешто, повторувањата без идемпотентност се човечки проблем маскиран како проблем на дистрибуирани системи: некој на крајот мора да објасни и да поправи дупликати.
Клучот за идемпотентност му овозможува на клиентот да изрази дека повторените поднесувања претставуваат едно наменето дејство. Серверот го зачувува клучот со соодветен опсег и го враќа првичниот резултат за последователни барања што се совпаѓаат. Точниот период на задржување и правилата за совпаѓање на барањата се одлуки за производот, но мора да бидат документирани. Повторната употреба на клуч со различни податоци за барањето не треба тивко да даде неповрзан резултат.
POST /v1/orders HTTP/1.1
Idempotency-Key: 9d8b2f0a-unique-client-key
Content-Type: application/json
{"customer_id":"cus_123","items":[{"sku":"book-42","quantity":1}]}
Идемпотентноста не е замена за трансакции, ограничувања на единственост или внимателни транзиции на состојби. Во PHP-бекенд, апликацискиот слој може да го координира барањето, но базата на податоци треба да ги наметне критичните инваријанти. Ако два работници се натпреваруваат да резервираат ист инвентар, само пријателски метод на контролер не е последната линија на одбрана.
Верзионирајте за промена, а не за церемонија
Секој API еволуира. Прашањето е дали еволуира на начин што им овозможува на потрошувачите намерно да се приспособат. Дополнителните промени обично полесно се прифаќаат од отстранувањата или промените во значењето, но дури и ново поле може да биде нарушувачко ако клиентите прават кршливи претпоставки за објектите во одговорот.
Пред да промените договор, идентификувајте ги вистинските потрошувачи и нивната толеранција на промени. Известувањата за застарување, водичите за миграција и реалистичниот период на премин се дел од имплементацијата, а не документациски обврски што треба да се одложат. Ако новото однесување го менува значењето, експлицитната граница на верзијата може да биде појасна од збир на знаменца чии интеракции никој не може самоуверено да ги објасни.
Миграциите на базата на податоци ја заслужуваат истата воздржаност. Распоредувањето код што очекува нова колона пред таа колона да постои може да не успее; отстранувањето стара колона додека сè уште работат постари инстанци на апликацијата може да не успее исто толку лесно. Побезбеден образец е прошири, мигрирај, потоа стесни:
- Додадете го новиот елемент на шемата во миграција компатибилна наназад.
- Распоредете код што може да ги чита старите и новите претставувања каде што е потребно.
- Пополнете ги наназад или мигрирајте ги податоците со набљудлива работа што може повторно да се стартува.
- Преместете ги сите потрошувачи на новото однесување.
- Отстранете ја старата патека само откако повеќе не се користи.
Оперативната јасност е дел од интерфејсот
Docker и автоматизацијата на распоредувањето можат да направат услуга репродуцибилна, но не ја прават автоматски разбирлива. Контејнерот треба да прима конфигурација преку експлицитни поставки на околината или управувани тајни, да запишува структурирани логови на стандарден излез и јасно да откаже кога потребната зависност не е достапна. Избегнувајте да го третирате рестартирањето на контејнер како универзална стратегија за опоравување; повторените рестартирања можат да сокријат лоша миграција, исцрпен пул на врски или неважечка конфигурација.
Перформансите ја заслужуваат истата перспектива насочена кон луѓето. Оптимизирајте ја работата што корисниците навистина ја доживуваат: бавни крајни точки за листи, извоз што трае долго, скапи проверки на овластување и барања кон базата на податоци што растат со обемот на податоци. Мерете пред да ја менувате архитектурата. Кешот може да ја подобри латентноста, но создава и правила за поништување и очекувања за застарени податоци што повикувачите можеби треба да ги разберат.
Во PHP-апликации, одржувајте ги доволно одделни транспортните грижи, доменските правила и деталите за перзистенција, така што секое од нив може да се тестира и менува без да ги повлекува другите со себе. Контролерот треба да преведе HTTP-барање во апликациско дејство, а не да стане единственото место каде што постојат деловните инваријанти. Јасните граници го прават API полесен за еволуирање, бидејќи договорот не е испреплетен со секое барање и детал на рамката.
Трајното дизајнерско прашање
API насочен кон луѓето не ветува дека интеграцијата ќе биде без напор. Вистинските системи имаат дозволи, неуспеси, асинхрона работа и спротивставени барања. Ветува нешто покорисно: тешките делови се видливи, кохерентни и поправливи.
Кога ја дизајнирате следната крајна точка, прашајте што ќе му треба на способен развивач во 2 часот наутро за време на инцидент. Дали може да го разбере одговорот? Дали може безбедно да се обиде повторно? Дали може да утврди дали промената е компатибилна? Дали може да проследи неуспех без да нагаѓа? Ако одговорот е да, API се поместил надвор од самото изложување алгоритам. Станал интерфејс на кој луѓето можат да му веруваат.