mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-03-17 20:42:26 +02:00
Replaced some punctuation marks and orthography
This commit is contained in:
parent
f450d87184
commit
8b3a1b8456
@ -10,7 +10,7 @@
|
||||
2. Каждый стакан кофе приготовлен по определённому *рецепту*, что подразумевает наличие разных ингредиентов и последовательности выполнения шагов приготовления.
|
||||
3. Напиток готовится на конкретной физической *кофе-машине*, располагающейся в какой-то точке пространства.
|
||||
|
||||
Каждый из этих уровней задаёт некоторый срез нашего API, с которым будет работать потребитель. Выделяя иерархию абстракций мы прежде всего стремимся снизить связность различных сущностей нашего API. Это позволит нам добиться нескольких целей.
|
||||
Каждый из этих уровней задаёт некоторый срез нашего API, с которым будет работать потребитель. Выделяя иерархию абстракций мы, прежде всего, стремимся снизить связность различных сущностей нашего API. Это позволит нам добиться нескольких целей.
|
||||
|
||||
1. Упрощение работы разработчика и легкость обучения: в каждый момент времени разработчику достаточно будет оперировать только теми сущностями, которые нужны для решения его задачи; и наоборот, плохо выстроенная изоляция приводит к тому, что разработчику нужно держать в голове множество концепций, не имеющих прямого отношения к решаемой задаче.
|
||||
|
||||
@ -306,7 +306,7 @@ POST /v1/runtimes
|
||||
"command_sequence_id",
|
||||
// Чем закончилось исполнение программы
|
||||
// (необязательное)
|
||||
// * "success" — напиток приготовлен и взят
|
||||
// * "success" — напиток приготовлен и выдан
|
||||
// * "terminated" — исполнение остановлено
|
||||
// * "technical_error" — ошибка при приготовлении
|
||||
// * "waiting_time_exceeded" — готовый заказ был
|
||||
@ -322,7 +322,7 @@ POST /v1/runtimes
|
||||
* либо обработчик `POST /orders` сам обращается к доступной информации о рецепте, кофе-машине и программе и формирует stateless-запрос, в котором указаны все нужные данные (тип API кофе-машины и список команд в частности);
|
||||
* либо в запросе содержатся только идентификаторы, и следующие обработчики в цепочке сами обратятся за нужными данными через какие-то внутренние API.
|
||||
|
||||
Оба варианта имеют право на жизнь; какой из них выбрать — зависит от деталей реализации.
|
||||
Оба варианта имеют право на жизнь; какой из них выбрать зависит от деталей реализации.
|
||||
|
||||
#### Изоляция уровней абстракции
|
||||
|
||||
@ -334,14 +334,14 @@ POST /v1/runtimes
|
||||
* обработчик `runs` в свою очередь выполнит операции своего уровня (в частности, проверит тип API кофе-машины) и в зависимости от типа API пойдёт по одной из двух веток исполнения:
|
||||
* либо вызовет `GET /execution/status` физического API кофе-машины, получит объём кофе и сличит с эталонным;
|
||||
* либо обратится к `GET /v1/runtimes/{runtime_id}`, получит `state.status` и преобразует его к статусу заказа;
|
||||
* в случае API второго типа цепочка продолжится: обработчик `GET /runtimes` обратится к физическому API `GET /sensors` и произведёт ряд манипуляций: сличит объём стакана / молотого кофе / налитой воды с запрошенным и при необходимости изменит состояние и статус.
|
||||
* в случае API второго типа цепочка продолжится: обработчик `GET /runtimes` обратится к физическому API `GET /sensors` и произведёт ряд манипуляций: сопоставит объём стакана / молотого кофе / налитой воды с запрошенным и при необходимости изменит состояние и статус.
|
||||
|
||||
**NB**: слова «цепочка вызовов» не следует воспринимать буквально. Каждый уровень может быть технически организован по-разному:
|
||||
* можно явно проксировать все вызовы по иерархии;
|
||||
* можно кэшировать статус своего уровня и обновлять его по получению обратного вызова или события.
|
||||
* можно кэшировать статус своего уровня и обновлять его по получении обратного вызова или события.
|
||||
В частности, низкоуровневый цикл исполнения рантайма для машин второго рода очевидно должен быть независимым и обновлять свой статус в фоне, не дожидаясь явного запроса статуса.
|
||||
|
||||
Обратите внимание, что здесь фактически происходит следующее: на каждом уровне абстракции есть какой-то свой статус (заказа, рантайма, сенсоров), который сформулирован в терминах соответствующей этому уровню абстракции предметной области. Запрет «перепрыгивания» уровней приводит к тому, что нам необходимо дублировать статус на каждом уровне независимо.
|
||||
Обратите внимание, что здесь фактически происходит следующее: на каждом уровне абстракции есть какой-то свой статус (заказа, рантайма, сенсоров), который сформулирован в терминах соответствующей этому уровню абстракции предметной области. Запрет «перепрыгивания» уровней приводит к тому, что нам необходимо независимо дублировать статус на каждом уровне.
|
||||
|
||||
Рассмотрим теперь, каким образом через наши уровни абстракции «прорастёт» операция отмены заказа. В этом случае цепочка вызовов будет такой:
|
||||
|
||||
@ -368,7 +368,7 @@ POST /v1/runtimes
|
||||
|
||||
Может показаться, что соблюдение правила изоляции уровней абстракции является избыточным и заставляет усложнять интерфейс. И это в действительности так: важно понимать, что никакая гибкость, логичность, читабельность и расширяемость не бывает бесплатной. Можно построить API так, чтобы оно выполняло свою функцию с минимальными накладными расходами, по сути — дать интерфейс к микроконтроллерам кофе-машины. Однако пользоваться им будет крайне неудобно, и расширяемость такого API будет нулевой.
|
||||
|
||||
Выделение уровней абстракции — прежде всего _логическая_ процедура: как мы объясняем себе и разработчику, из чего состоит наш API. **Абстрагируемая дистанция между сущностями существует объективно**, каким бы образом мы ни написали конкретные интерфейсы. Наша задача состоит только лишь в том, чтобы эта дистанция была разделена на уровни _явно_. Чем более неявно разведены (или, хуже того, перемешаны) уровни абстракции, тем сложнее будет разобраться в вашем API, и тем хуже будет написан использующий его код.
|
||||
Выделение уровней абстракции, прежде всего, _логическая_ процедура: как мы объясняем себе и разработчику, из чего состоит наш API. **Абстрагируемая дистанция между сущностями существует объективно**, каким бы образом мы ни написали конкретные интерфейсы. Наша задача состоит только лишь в том, чтобы эта дистанция была разделена на уровни _явно_. Чем более неявно разведены (или, хуже того, перемешаны) уровни абстракции, тем сложнее будет разобраться в вашем API, и тем хуже будет написан использующий его код.
|
||||
|
||||
#### Потоки данных
|
||||
|
||||
@ -399,4 +399,4 @@ POST /v1/runtimes
|
||||
* с одной стороны, в контексте заказа оказываются данные (объём кофе), «просочившиеся» откуда-то с физического уровня; тем самым, уровни абстракции непоправимо смешиваются без возможности их разделить;
|
||||
* с другой стороны, сам контекст заказа неполноценный: он не задаёт новых мета-переменных, которые отсутствуют на более низких уровнях абстракции (статус заказа), не инициализирует их и не предоставляет правил работы.
|
||||
|
||||
Более подробно о контекстах данных мы поговорим в разделе II. Здесь же ограничимся следующим выводом: потоки данных и их преобразования можно и нужно рассматривать как некоторый срез, который, с одной стороны, помогает нам правильно разделить уровни абстракции, а с другой — проверить, что наши теоретические построения действительно работают так, как нужно.
|
||||
Более подробно о контекстах данных мы поговорим в разделе II. Здесь же ограничимся следующим выводом: потоки данных и их преобразования можно и нужно рассматривать как некоторый срез, который, с одной стороны, помогает нам правильно разделить уровни абстракции, а с другой — проверить, что наши теоретические построения действительно работают так, как нужно.
|
||||
|
Loading…
x
Reference in New Issue
Block a user