REST и API design на собеседовании системного аналитика
Зачем SA спрашивают про REST и API
REST и API-контракты — это язык, на котором сервисы общаются. SA не пишет код, но проектирует endpoints, формулирует contracts, описывает edge cases. Без этого нельзя интегрировать новый сервис, нельзя протестировать, нельзя поддерживать.
На собесе системного аналитика API-design — обязательный блок, обычно отдельный раунд 60-90 минут. Уровень: junior — знает HTTP-методы и статусы; middle — спроектирует endpoint с обработкой ошибок; senior — поддерживает API на масштабе с versioning и обратной совместимостью.
HTTP-основы
Методы:
- GET — чтение. Не должен менять state. Идемпотентен.
- POST — создание. Не идемпотентен (если нет idempotency-key).
- PUT — полная замена ресурса. Идемпотентен.
- PATCH — частичное обновление. Семантически идемпотентен (при тех же данных).
- DELETE — удаление. Идемпотентен.
Статусы:
- 2xx success: 200 OK, 201 Created, 202 Accepted (async), 204 No Content
- 3xx redirect: 301 Moved Permanently, 302 Found, 304 Not Modified
- 4xx client error: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests
- 5xx server error: 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
Важно различать: 401 — не залогинен; 403 — залогинен, но нет прав; 404 — ресурс не существует.
REST принципы
Resource-based URLs. /users/123/orders/456, не /getUserOrder?userId=123&orderId=456.
Stateless. Каждый запрос самодостаточен. Сервер не хранит session state (или хранит в shared store).
Cacheable. Ответы помечают cache headers (Cache-Control, ETag).
Uniform interface. Согласованные методы и форматы.
Layered system. Клиент не знает, общается ли он с конечным сервисом или через proxy/gateway.
HATEOAS (опционально) — ответ содержит ссылки на возможные следующие действия.
Идемпотентность
Многократный вызов даёт тот же результат. Критично для retry-логики, особенно в платёжных системах.
Идемпотентные методы: GET, PUT, DELETE.
Не идемпотентен по природе: POST.
Как сделать POST идемпотентным:
- Idempotency-Key header. Клиент генерирует UUID, сервер дедуплицирует.
POST /payments Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 - Client-supplied ID. Клиент даёт ID. Сервер UPSERT по нему.
- Optimistic locking. Versioning + If-Match header.
Версионирование API
URL versioning: /v1/users/123. Самый простой, явный.
Header versioning: Accept: application/vnd.api.v1+json. Cleaner URLs, сложнее в debug.
Query parameter: /users/123?version=1. Редко.
Breaking vs non-breaking changes:
Non-breaking (минор-релиз):
- Добавление нового optional поля в response
- Добавление нового endpoint
- Добавление нового optional query parameter
Breaking (мажор-релиз, новая версия):
- Удаление или переименование поля
- Изменение типа поля
- Изменение обязательности
- Изменение URL структуры
Стратегия: держим N-1 версию. Объявляем deprecation за 6 месяцев. После — отключаем.
REST vs gRPC vs GraphQL
| REST | gRPC | GraphQL | |
|---|---|---|---|
| Формат | JSON / XML | Protocol Buffers (binary) | JSON |
| Транспорт | HTTP/1.1 / 2 | HTTP/2 | HTTP/1.1 / WebSocket |
| Контракт | OpenAPI (опционально) | .proto (обязательно) | Schema (обязательно) |
| Производительность | средняя | высокая | средняя |
| Доступ из браузера | да | через grpc-web | да |
| Use case | публичный API | service-to-service | UI-API |
На собесе: «По умолчанию REST для публичных API, gRPC для internal сервис-к-сервису, GraphQL для UI/aggregation».
Дизайн endpoint: чек-лист
Спросите перед написанием endpoint:
- Resource model. Какие сущности?
- URL.
/orders/{id}— единственное число существ.,/orders— список - Метод. Какой HTTP-method подходит по семантике?
- Request schema. Какие поля, типы, обязательность?
- Response schema. Что возвращаем при success? Кодировка ошибок?
- Статусы. Все возможные HTTP-статусы и когда они отдаются
- Идемпотентность. Если POST — нужен ли idempotency?
- Authorization. Кто может вызвать? Какие scope?
- Rate limiting. Лимиты по клиенту/endpoint?
- Версионирование. v1 / v2 / header?
Обработка ошибок
Структура error response:
{
"error": {
"code": "INVALID_AMOUNT",
"message": "Amount must be positive",
"field": "amount",
"request_id": "abc-123"
}
}Принципы:
- HTTP-статус соответствует категории ошибки
- Body — human-readable + machine-parseable error code
- Не leak internal details (stack trace, SQL)
- request_id для трассировки
Типичные вопросы
«Спроектируй endpoint оформления заказа»
POST /orders
Idempotency-Key: <UUID>
Authorization: Bearer <token>
Body:
{
"customer_id": "...",
"items": [{"product_id": "...", "quantity": 1}],
"delivery_address": {...},
"payment_method": "card"
}
Responses:
201 Created → { "order_id": "...", "status": "pending" }
400 Bad Request → invalid input (e.g., negative quantity)
401 Unauthorized → invalid token
402 Payment Required → insufficient funds
404 Not Found → product not found
409 Conflict → already created with this idempotency key
422 Unprocessable → out of stock
429 Too Many Requests → rate limit
500 Internal Server Error → unexpected«Что вернёт сервер, если клиент дважды отправил один POST?»
С idempotency-key: вернёт тот же 201 (уже созданный). Без — создаст два заказа (баг). Без idempotency-key платежи нельзя.
«REST vs gRPC: когда что?»
REST для публичных, человекочитаемых, любая платформа. gRPC для service-to-service, где важна скорость и сильная типизация.
«Чем PUT отличается от PATCH?»
PUT — полная замена ресурса. PATCH — частичное изменение. PUT обязан передать всё, PATCH — только дельту. По стандарту оба идемпотентны.
«Как версионировать публичный API без breaking changes на год?»
(1) Семантическое версионирование (major.minor.patch). (2) Добавлять только non-breaking. (3) Deprecation policy: помечать поля как @deprecated, удалять только в major. (4) Параллельный support N-1 версии.
Частые ошибки
- Использовать GET для side-effects. GET должен быть безопасным.
/api/users/delete?id=1— нарушение. - Игнорировать идемпотентность. Без idempotency POST = дубликаты при retry.
- Все ошибки 500. Чтобы клиент мог обработать — корректные 4xx/5xx.
- Версионирование через path для всего. Иногда лучше header или content negotiation.
- Дизайн без error schema. Клиент должен парсить ошибки программно, не только читать message.
FAQ
REST vs RESTful?
REST — архитектурный стиль. RESTful — API, который ему следует. На практике «REST» обычно означает «HTTP+JSON API», без полного соответствия принципам Roy Fielding.
Спрашивают ли HATEOAS?
Редко. В production почти не используется.
Что такое OpenAPI?
Спецификация для описания REST API. Раньше — Swagger. Используется для документации, генерации клиентов, моков.
Сколько готовиться?
Junior — 1-2 месяца. Middle/Senior — 2-4 недели для систематизации.
Какие книги?
«REST API Design Rulebook» (Masse) — фундамент. «Designing Data-Intensive Applications» (Kleppmann) — глобальный контекст.