You've already forked The-API-Book
mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-08-10 21:51:42 +02:00
corrections
This commit is contained in:
@@ -123,6 +123,7 @@ pre {
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.img-wrapper img {
|
||||
@@ -140,7 +141,6 @@ pre {
|
||||
box-sizing: border-box;
|
||||
page-break-inside: avoid;
|
||||
overflow-x: auto;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
img:not(.cc-by-nc-img) {
|
||||
|
@@ -998,7 +998,7 @@ POST /v1/orders/
|
||||
PATCH /v1/orders/{id}
|
||||
{
|
||||
"items": [null, {
|
||||
"volume": "800ml"
|
||||
"volume": "800ml"
|
||||
}]
|
||||
}
|
||||
→
|
||||
@@ -1022,7 +1022,6 @@ PATCH /v1/orders/{id}
|
||||
|
||||
**Лучше**: разделить эндпойнты. Редактируемые поля группируются и выносятся в отдельный эндпойнт. Этот подход также хорошо согласуется [с принципом декомпозиции](#chapter-10), который мы рассматривали в предыдущем разделе.
|
||||
|
||||
```
|
||||
```
|
||||
// Создаёт заказ из двух напитков
|
||||
POST /v1/orders/
|
||||
@@ -1050,6 +1049,7 @@ POST /v1/orders/
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
// Изменяет параметры заказа
|
||||
PUT /v1/orders/{id}/parameters
|
||||
@@ -1057,6 +1057,7 @@ PUT /v1/orders/{id}/parameters
|
||||
→
|
||||
{ "delivery_address" }
|
||||
```
|
||||
|
||||
```
|
||||
// Частично перезаписывает заказ
|
||||
// обновляет объём второго напитка
|
||||
@@ -1065,15 +1066,16 @@ PUT /v1/orders/{id}/items/{item_id}
|
||||
→
|
||||
{ "recipe", "volume", "milk_type" }
|
||||
```
|
||||
```
|
||||
|
||||
Теперь для удаления `volume` достаточно *не* передавать его в `PUT items/{item_id}`. Этот подход также позволяет отделить неизменяемые и вычисляемые поля (`created_at` и `status`) от изменяемых, не создавая двусмысленных ситуаций (что произойдёт, если клиент попытается изменить `created_at`?). В этом подходе также можно в ответах операций `PUT` возвращать объект заказа целиком (однако следует использовать какую-то конвенцию именования), а не только изменённые суб-объекты.
|
||||
|
||||
**NB**: при декомпозиции эндпойнтов велик соблазн провести границу так, чтобы разделить изменяемые и неизменяемые данные. Тогда последние можно объявить кэшируемыми условно вечно и вообще не думать над проблемами пагинации и формата обновления. На бумаге план выглядит отлично, однако с ростом API неизменяемые данные частенько перестают быть таковыми, и вся концепция не только перестаёт работать, но и выглядит как плохой дизайн. Мы скорее рекомендуем объявлять данные иммутабельными в одном из двух случаев: либо (1) они действительно не могут стать изменяемыми без слома обратной совместимости, либо (2) ссылка на ресурс (например, на изображение) поступает через API же, и вы обладаете возможностью сделать эти ссылки персистентными (т.е. при необходимости обновить изображение будете генерировать новую ссылку, а не перезаписывать контент по старой ссылке).
|
||||
|
||||
**Ещё лучше**: разработать формат описания атомарных изменений.
|
||||
|
||||
```
|
||||
POST /v1/order/changes
|
||||
X-Idempotency-Token: <см. следующий раздел>
|
||||
X-Idempotency-Token: <токен идемпотентности>
|
||||
{
|
||||
"changes": [{
|
||||
"type": "set",
|
||||
@@ -1128,7 +1130,7 @@ X-Idempotency-Token: <см. следующий раздел>
|
||||
|
||||
Следует иметь в виду, что явной передачи локации может оказаться недостаточно, поскольку в мире существуют территориальные конфликты и спорные территории. Каким образом API должен себя вести при попадании координат пользователя на такие территории — вопрос, к сожалению, в первую очередь юридический. Автору этой книги приходилось как-то разрабатывать API, в котором пришлось вводить концепцию «территория государства A по мнению официальных органов государства Б».
|
||||
|
||||
**Важно**: различайте локализацию для конечного пользователя и локализацию для разработчика. В примере из п. 19 сообщение `localized_message` адресовано пользователю — его должно показать приложение, если в коде обработка такой ошибки не предусмотрена. Это сообщение должно быть написано на указанном в запросе языке и отформатировано согласно правилам локации пользователя. А вот сообщение `details.checks_failed[].message` написано не для пользователя, а для разработчика, который будет разбираться с проблемой. Соответственно, написано и отформатировано оно должно быть понятным для разработчика образом — что, скорее всего, означает «на английском языке», т.к. английский де-факто является стандартом в мире разработки программного обеспечения.
|
||||
**Важно**: различайте локализацию для конечного пользователя и локализацию для разработчика. В примере из п. 12 сообщение `localized_message` адресовано пользователю — его должно показать приложение, если в коде обработка такой ошибки не предусмотрена. Это сообщение должно быть написано на указанном в запросе языке и отформатировано согласно правилам локации пользователя. А вот сообщение `details.checks_failed[].message` написано не для пользователя, а для разработчика, который будет разбираться с проблемой. Соответственно, написано и отформатировано оно должно быть понятным для разработчика образом — что, скорее всего, означает «на английском языке», т.к. английский де-факто является стандартом в мире разработки программного обеспечения.
|
||||
|
||||
Следует отметить, что индикация, какие сообщения следует показать пользователю, а какие написаны для разработчика, должна, разумеется, быть явной конвенцией вашего API. В примере для этого используется префикс `localized_`.
|
||||
|
||||
|
1134
src/ru/drafts/05.md
1134
src/ru/drafts/05.md
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user