1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-08-10 21:51:42 +02:00

Chapter 11 refactoring - continued

This commit is contained in:
Sergey Konstantinov
2022-09-07 09:29:36 +03:00
committed by GitHub
parent 74ee3a44cf
commit adbd991bcc

View File

@@ -4,9 +4,9 @@
Важное уточнение под номером ноль:
##### 0. Правила — это всего лишь обобщения
##### 0. Правила не должны применяться бездумно
Правила не действуют безусловно и не означают, что можно не думать головой. У каждого правила есть какая-то рациональная причина его существования. Если в вашей ситуации нет причин следовать правилу — значит, следовать ему не нужно.
Правила — это просто крастно сформулированное обобщение опыта. Они не действуют безусловно и не означают, что можно не думать головой. У каждого правила есть какая-то рациональная причина его существования. Если в вашей ситуации нет причин следовать правилу — значит, следовать ему не нужно.
Например, требование консистентности номенклатуры существует затем, чтобы разработчик тратил меньше времени на чтение документации; если вам _необходимо_, чтобы разработчик обязательно прочитал документацию по какому-то методу, вполне разумно сделать его сигнатуру нарочито неконсистентно.
@@ -16,7 +16,7 @@
#### Читабельность и консистентность
Важнейшая задача разработчика API — добиться того, чтобы код, написанный поверх API сторонними разработчиками, легко читался и поддерживался. Помните, что в случае API закон больших чисел неизбежно работает против вас: если какую-то концепцию или сигнатуру вызова можно понять неправильно, то с ростом числа потребителей API будет расти и количество неправильно понявших принципы программистов, а значит и количество плохо работающего кода, ошибки в котором будут видны конечным пользователям.
Важнейшая задача разработчика API — добиться того, чтобы код, написанный поверх API сторонними разработчиками, легко читался и поддерживался. Помните, что закон больших чисел работает против вас: если какую-то концепцию или сигнатуру вызова можно понять неправильно, значит, её неизбежно будет понимать неправильно всё большее число разработчиков по мере роста популярности API.
##### Явное лучше неявного
@@ -59,7 +59,7 @@ POST /v1/orders/statistics/aggregate
##### Указывайте использованные стандарты
К сожалению, человечество не в состоянии договориться о таких простейших вещах, как «с какого дня начинается неделя». Поэтому _всегда_ указывайте, по какому конкретно стандарту вы отдаёте те или иные величины. Исключения возможны только там, где вы на 100% уверены, что в мире существует только один стандарт для этой сущности, и всё население земного шара о нём в курсе.
К сожалению, человечество не в состоянии договориться о таких простейших вещах, как «с какого дня начинается неделя». Поэтому *всегда* указывайте, по какому конкретно стандарту вы отдаёте те или иные величины. Исключения возможны только там, где вы на 100% уверены, что в мире существует только один стандарт для этой сущности, и всё население земного шара о нём в курсе.
**Плохо**: `"date": "11/12/2020"` — существует огромное количество стандартов записи дат, плюс из этой записи невозможно даже понять, что здесь число, а что месяц.
@@ -210,7 +210,9 @@ if (Type(order.contactless_delivery) == 'Boolean' &&
Эта практика ведёт к усложнению кода, который пишут разработчики, и в этом коде легко допустить ошибку, которая по сути меняет значение поля на противоположное. То же самое произойдёт, если для индикации отсутствия значения поля использовать специальное значение типа `null` или `-1`.
В этих ситуациях универсальное правило — все новые необязательные булевы флаги должны иметь значение по умолчанию false.
**NB**. Это замечание не распространяется на те случае, когда платформа и протокол однозначно и без всяких дополнительных абстракций поддерживают такие специальные значения для сброса значения поля в значение по умолчанию. Однако полная и консистентная поддержка частичных операций со сбросом значений полей практически нигде не имплементирована. Пожалуй, единственный пример такого API из имеющих широкое распространение сегодня — SQL: в языке есть и концепция `NULL`, и значения полей по умолчанию, и поддержка конструкций вида `UPDATE … SET field = DEFAULT` (в большинстве диалектов). Хотя работа с таким протоколом всё ещё затруднена (например, во многих диалектах нет простого способа получить обратно значение по умолчанию, которое выставил `UPDATE`), частичные обновления в нём имплементированы достаточно хорошо, чтобы использовать их без дополнительных уточнений.
Если же протоколом явная работа со значениями по умолчанию не предусмотрена, универсальное правило — все новые необязательные булевы флаги должны иметь значение по умолчанию false.
**Хорошо**
```
@@ -500,6 +502,29 @@ GET /v1/orders/{id}
GET /v1/users/{id}/orders
```
Это правило так же распространяется и на ошибки, в первую очередь, клиентские. Если ошибку можно исправить, информация об этом должна быть машиночитаема.
**Плохо**: `{"error": "email malformed"}`
— единственное, что может с этой ошибкой сделать разработчик — показать её пользователю
**Хорошо**:
```
{
// Machine-readable
"status": "validation_failed",
// An array; if there are several
// errors, the user might correct
// them all at once
"failed_checks": [
{
"field: "email",
"error_type": "malformed",
// Localized human-readable message
"message": "email malformed"
}
]
}
```
##### Пагинация, фильтрация и курсоры
Любой эндпойнт, возвращающий массивы данных, должен содержать пагинацию. Никаких исключений в этом правиле быть не может.
@@ -877,10 +902,12 @@ PATCH /v1/recipes
**Во-первых**, почти всегда процедуры, обеспечивающие безопасность той или иной операции, *уже разработаны*. Нет никакой нужды придумывать их заново, просто имплементируйте какой-то из существующих протоколов. Никакие самописные алгоритмы проверки сигнатур запросов не обеспечат вам того же уровня защиты от атаки Man-in-the-Middle, как соединение по протоколу TLS с взаимной проверкой сигнатур сертификатов.
**Во-вторых**, чрезвычайно самонадеянно (и опасно) считать, что вы разбираетесь в вопросах безопасности. Новые вектора атаки появляются каждый день, и быть в курсе всех актуальных проблем — это само по себе работа на полный рабочий день.
**Во-вторых**, чрезвычайно самонадеянно (и опасно) считать, что вы разбираетесь в вопросах безопасности. Новые вектора атаки появляются каждый день, и быть в курсе всех актуальных проблем — это само по себе работа на полный рабочий день. Если же вы полный рабочий день занимаетесь чем-то другим, спроектированная вами система защиты наверняка будет содержать уязвимости, о которых вы просто никогда не слышали — например, ваш алгоритм проверки паролей может быть подвержен [атаке по времени](https://en.wikipedia.org/wiki/Timing_attack), а веб-сервер — [атаке с разделением запросов](https://capec.mitre.org/data/definitions/105.html).
##### Считайте трафик
В современном мире
##### Избегайте неявных частичных обновлений
**Плохо**: