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:
parent
a79c85cebb
commit
1274f6e148
@ -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.
|
||||
|
@ -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 (рецептов) станет невозможно пользоваться без другой части (информации о кофемашинах). Что немаловажно, от разработчиков потребуется изменить логику своего приложения: если раньше они могли предлагать сначала выбрать объём, а потом кофемашину, то теперь им придётся полностью изменить этот шаг.
|
||||
|
||||
Хорошо, допустим, мы поняли, как сделать плохо. Но как же тогда сделать *хорошо*? Разделение уровней абстракции должно происходить вдоль трёх направлений:
|
||||
|
Loading…
x
Reference in New Issue
Block a user