1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-05-19 21:33:04 +02:00

clarifications

This commit is contained in:
Sergey Konstantinov 2023-03-04 11:19:54 +02:00 committed by GitHub
parent a79c85cebb
commit 1274f6e148
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 1 deletions

View File

@ -62,7 +62,6 @@ GET /v1/orders/{id}
}
```
Then a developer just needs to compare two numbers to find out whether the order is ready.
This solution intuitively looks bad, and it really is: it violates all the abovementioned principles.

View File

@ -41,6 +41,23 @@ GET /v1/orders/{id}
И зададимся вопросом, каким образом разработчик определит, что заказ клиента готов. Допустим, мы сделаем так: добавим в рецепт лунго эталонный объём, а в состояние заказа — количество уже налитого кофе. Тогда разработчику нужно будет проверить совпадение этих двух цифр, чтобы убедиться, что кофе готов.
```
GET /v1/recipes/lungo
{
"volume": "100ml"
}
```
```
GET /v1/orders/{id}
{
"volume": "80ml"
}
```
Такое решение выглядит интуитивно плохим, и это действительно так: оно нарушает все вышеперечисленные принципы.
**Во-первых**, для решения задачи «заказать лунго» разработчику нужно обратиться к сущности «рецепт» и выяснить, что у каждого рецепта есть объём. Далее, нужно принять концепцию, что приготовление кофе заканчивается в тот момент, когда объём сравнялся с эталонным. Нет никакого способа об этой конвенции догадаться: она неочевидна и её нужно найти в документации. При этом никакой пользы для разработчика в этом знании нет.
@ -62,6 +79,22 @@ POST /v1/orders
* разработчик, которому придётся поддержать эту функциональность, имеет высокие шансы сделать ошибку: добавив поддержку произвольного объёма кофе в код, работающий с `POST /v1/orders` нужно не забыть переписать код проверки готовности заказа;
* мы получим классическую ситуацию, когда одно и то же поле (объём кофе) значит разные вещи в разных интерфейсах. В `GET /v1/recipes` поле «объём» теперь значит «объём, который будет запрошен, если не передать его явно в `POST /v1/orders`»; переименовать его в «объём по умолчанию» уже не получится, с этой проблемой теперь придётся жить.
Мы получим:
```
GET /v1/orders/{id}
{
// Это текущий объём кофе,
// который наследует имя поля
// из старого интерфейса
"volume": "80ml",
// а это объём кофе, запрошенный
// пользователем
"volume_requested": "800ml"
}
```
**В-третьих**, вся эта схема полностью неработоспособна, если разные модели кофемашин производят лунго разного объёма. Для решения задачи «объём лунго зависит от вида машины» нам придётся сделать совсем неприятную вещь: сделать рецепт зависимым от id машины. Тем самым мы начнём активно смешивать уровни абстракции: одной частью нашего API (рецептов) станет невозможно пользоваться без другой части (информации о кофемашинах). Что немаловажно, от разработчиков потребуется изменить логику своего приложения: если раньше они могли предлагать сначала выбрать объём, а потом кофемашину, то теперь им придётся полностью изменить этот шаг.
Хорошо, допустим, мы поняли, как сделать плохо. Но как же тогда сделать *хорошо*? Разделение уровней абстракции должно происходить вдоль трёх направлений: