Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Что не так с REST
Search
Deep Refactoring
August 31, 2017
Education
0
180
Что не так с REST
Иван Гришаев
Deep Refactoring
August 31, 2017
Tweet
Share
More Decks by Deep Refactoring
See All by Deep Refactoring
Поворот на 90°
deeprefactoring
0
110
Card Payments 101
deeprefactoring
0
89
Звонки на стероидах
deeprefactoring
0
79
Make Time
deeprefactoring
0
66
Learn-to-Rank или как научить бездушную машину хорошо искать
deeprefactoring
0
110
Уменьшаем количество рефлексии в коде
deeprefactoring
1
51
Прикладная кодогенерация для Java разработчика
deeprefactoring
0
330
Пишем игровой навык для Алисы Яндекс с помощью Excel
deeprefactoring
0
120
Подружиться с исключениями. Иван Гришаев, Exoscale
deeprefactoring
0
110
Other Decks in Education
See All in Education
小・中・高等学校における情報教育の体系的な学習を目指したカリキュラムモデル案/curriculum model
codeforeveryone
2
2.3k
老人会? いえ、技術継承です @ builderscon 2024 LT
s3i7h
0
110
CSS3 and Responsive Web Design - Lecture 5 - Web Technologies (1019888BNR)
signer
PRO
1
2.5k
Tableau トレーニング【株式会社ニジボックス】
nbkouhou
0
19k
Chapitre_1_-__L_atmosphère_et_la_vie_-_Partie_1.pdf
bernhardsvt
0
220
お仕事図鑑pitchトーク
tetsuyaooooo
0
2.3k
寺沢拓敬 2024. 09. 「言語政策研究と教育政策研究の狭間で英語教育政策を考える」
terasawat
0
200
Kaggle 班ができるまで
abap34
1
190
TP5_-_UV.pdf
bernhardsvt
0
100
HCI and Interaction Design - Lecture 2 - Human-Computer Interaction (1023841ANR)
signer
PRO
0
810
2409_CompanyInfo_Hanji_published.pdf
yosukemurata
0
370
Blogit opetuksessa
matleenalaakso
0
1.6k
Featured
See All Featured
The Cult of Friendly URLs
andyhume
78
6k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
Code Reviewing Like a Champion
maltzj
520
39k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Measuring & Analyzing Core Web Vitals
bluesmoon
4
120
Code Review Best Practice
trishagee
64
17k
Designing for Performance
lara
604
68k
Thoughts on Productivity
jonyablonski
67
4.3k
A Modern Web Designer's Workflow
chriscoyier
693
190k
KATA
mclloyd
29
14k
Gamification - CAS2011
davidbonilla
80
5k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Transcript
Что не так с REST Иван Гришаев, Глубокий рефакторинг
API Машинный интерфейс Автоматизация —> Машина —> Машина -X- Человек
-X- Машина —> Машина
API Выбор оператора Тип банковской карты Справки, документооборот Просто нет
нужной апишки
Минутка истории Первые API XML/SOAP XML/RPC WSDL
Минутка истории Интеграция с 1C Python/Suds JSON inside XML/SOAP https://github.com/igrishaev/1c-json
REST Де-факто в индустрии Все фреймворки по REST Масса утилит
(Swagger, RAML) Сервисы/сайты-API Священная корова
REST Не факт, что было задумано именно так Так уж
вышло Вложено много сил Все ли мы делаем правильно?
Неконкретика Что такое REST? Representational state transfer Method + Resource
+ ID
Неконкретика Как передать версию? /api/v1/users /api/users?version=1 "Version": "1" {"name": "Ivan",
"version": 1} (Как вообще версионировать? И нужно ли?)
Неконкретика CRUD are not enough PUT vs POST vs PATCH
Не отражает бизнес-логику
Роспуск группы DELETE /groups/42 Группа не удаляется Затрагиваются пользователи Пишется
история
Дать пользователю скидку POST /users/42/discount PUT /items/42/users/1 PATCH /promo {"user_id":
42, "discount": 10}
Неконкретика В крупных фирмах спеки Google: Resource Oriented Design У
вас стартап, вам некогда
Данные размазаны по всему запросу GET /api/users/?active=true HTTP/1.1 Version: 1
Authentication: Basic Base64String==
Данные размазаны по всему запросу PUT /api/users/1 HTTP/1.1 Version: 1
Authentication: Basic Base64String== {"name": "Ivan", "age": 31}
Данные размазаны по всему запросу Нет смысла Слишком большой скоуп
Такой Request трудно построить Только для веб-сервера верхнего уровня Чтение по частям
Неконкретика Когда GET, обрабатываю query string Когда другой, тело запроса
Нет одного источника данных
Какая разница? import boto import time s3 = boto.connect_s3() bucket
= s3.create_bucket('boto-demo-%s' % int(time.time())) key = bucket.new_key('mykey') key.set_contents_from_string("Hello World!") print key.get_contents_as_string() key.delete() bucket.delete()
Какая разница? String cleanBucketName = bucketName.replaceAll("/$", ""); String uri =
GCS_URI + cleanBucketName; HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(credential); GenericUrl url = new GenericUrl(uri); HttpRequest request = requestFactory.buildGetRequest(url); HttpResponse response = request.execute(); String content = response.parseAsString();
Кеш? Не нужно Чаще всего кеширование как раз не нужно
Костыли с random query arg Так и быть, разрешить GET + query string Varnish
Зависимость от классов from django.conf.urls import url, include from django.contrib.auth.models
import User from rest_framework import routers, serializers, viewsets class UserRest(BaseRestClass): def on_get(self, request): ... def on_put(self, request): ... def on_post(self, request): ... Как инициализировать класс? Как инициализировать Request? Как переиспользовать on_put?
Swagger Интерфейс Запрещает ошибки, а нам нужно Не сохраняет сессии
(Postman) Убог Вал зависимостей
Как нужно Главное — данные Data-oriented programming Мыслить в терминах
бизнес-логики Alan Kay and Rich Hickey about "data"
Request vs Data Запрос — это не данные, а состояние
Огромный скоуп (сокет, сессия, ...) Нельзя сохранить Данные — постоянны
SEA — single endpoint API Максимально абстрагироваться от транспорта Действие
и аргументы Все в одном месте
SEA — single endpoint API Действие — что делать На
сервере словарь "действие" ⇒ функция Одна функция-диспатчер
SEA — single endpoint API { "action": "list_users", "active_only": true,
# optional "order_by": "name", # optional "version": 1, "performer_id": 42, "signature": "671345234y6234" }
SEA — single endpoint API Метаданные В словаре не только
функции, но и схемы, права и тд
SEA — single endpoint API actions = { "get_user": {
"handler": api.get_user, "schema_in": schemas.get_user_in, "schema_out": schemas.get_user_out, "role": "admin", "doc": "Some API description", "added": "1.4.2", } }
Одна точка входа /users/ /users/42 /users/42/orders/ /order/ /order/42 /customer/ /customers/42
/customers/42/orders/
Одна точка входа А теперь еще клиент! var apiRoutes =
{ get_user: "/users/:id", list_users: "/users/", user_orders: "/users/:id/orders", ... }
Одна точка входа /api {"action": "create_user", "name": "Ivan", "age": 31}
/api {"action": "update_user", "user_id": 1, "name": "Juah"} /api {"action": "delete_order", "order_id": 42} ... 1 функция на сервере 1 функция на клиенте
Масштабируется Не нужно писать новый класс Не нужно добавлять новый
урл Просто новый ключ в словаре Версионирование по ключам (fallback)
Просто, понятно Данные Словари Функции
API знает все о себе Список всех апишек с доками
Рендер документации как нужно нам Апишка, которая возврашает апишки, схемы, метаданные
API знает все о себе список апишек {"action": "list_api"} документация
к апишке {"action": "get_doc", "target": "list_api"} схемы данных {"action": "get_schemas", "target": "get_doc"}
Сценарии {...}, {...}, {...} в файле, в коде VS GET
/users/42 HTTP/1.1 POST /users/ HTTP/1.1 {...} PUT /users/42 HTTP/1.1 {...}
Примеры Вконтакте https://api.vk.com/method/users.get?user_id=210700286&v=5.52 https://api.vk.com/method/pages.getTitles?v=5.51 https://api.vk.com/method/wall.deleteComment?comment_id=123123&v=5.51
Примеры Наш стартап {"action": "users/get", "user_id": 42} {"action": "users/update", "user_id":
42, "name": "Juan"}
Примеры actions = { "get_user": api_get_user, "update_user": api_update_user, "list_users": api_list_users
} def api_update_user(data): user_id = data.pop("user_id") Users.objects.update(data).filter(id=user_id) return response_ok()
Примеры (def action-rules {:displayfixtures/get-nearby {:handler #'nearby-displayfixtures :schema-in s/CQRSNearbyDisplayfixturesIn :schema-out s/CQRSNearbyDisplayfixturesOut}
:displayfixtures/get-all-displayfixtures {:handler #'get-all-displayfixtures :schema-in s/CQRSParams :schema-out s/CQRSGetAllDisplayfixturesOut}
Примеры (defmulti api :action) (defmethod api :users/get [{user_id :id}] ...)
(defmethod api :users/update [params] ...) (defmethod api :default [params] {:status 404})
Преткнования Это не REST!!! У нас так не принято Утилиты
Жалко потраченных сил
Что это дает Независимость от транспорта Очереди, таски, Async Сценарии,
обстрелы Масштабируемость Прозрачность Критичный взгляд
Ссылки From REST to CQRS https://www.youtube.com/watch?v=qDNPQo9UmJA https://martinfowler.com/bliki/CQRS.html https://news.ycombinator.com/item?id=11945722
Вопросы