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
100
Card Payments 101
deeprefactoring
0
81
Звонки на стероидах
deeprefactoring
0
75
Make Time
deeprefactoring
0
62
Learn-to-Rank или как научить бездушную машину хорошо искать
deeprefactoring
0
96
Уменьшаем количество рефлексии в коде
deeprefactoring
1
47
Прикладная кодогенерация для Java разработчика
deeprefactoring
0
290
Пишем игровой навык для Алисы Яндекс с помощью Excel
deeprefactoring
0
110
Подружиться с исключениями. Иван Гришаев, Exoscale
deeprefactoring
0
100
Other Decks in Education
See All in Education
A question of time
ange
0
730
week4@tcue2024
nonxxxizm
0
520
ポケモンで音象徴
jamashita
0
260
小・中・高等学校における情報教育の体系的な学習を目指したカリキュラムモデル案/curriculum model
codeforeveryone
0
230
世界の子音探訪記
jamashita
0
230
Matz に頼られたので張り切って2時間ほどドイツと日本の互いの Ruby 学習事情についてディスカッションした話
yasulab
1
320
2023年度「生成AI100校プロジェクト」 実践報告書/The 2023 "Generative AI 100 Schools Project" Practical Report
codeforeveryone
0
1.1k
【基本】Oracle Database データベース・ユーザー・セキュリティ入門
oracle4engineer
PRO
1
300
Pen-based Interaction - Lecture 4 - Next Generation User Interfaces (4018166FNR)
signer
PRO
0
1.4k
week15@tcue2024
nonxxxizm
0
380
Lecture on Management at Waseda University
tsogo817421
2
580
3Dプリンターの使い方(Sovol 06 Plus)
404background
0
150
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
42
2.7k
We Have a Design System, Now What?
morganepeng
46
7k
Agile that works and the tools we love
rasmusluckow
325
20k
Designing on Purpose - Digital PM Summit 2013
jponch
113
6.6k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
26
2.1k
Bash Introduction
62gerente
607
210k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
18
1.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
502
140k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
34
1.9k
Why You Should Never Use an ORM
jnunemaker
PRO
51
8.9k
Building Your Own Lightsaber
phodgson
101
5.9k
Building a Modern Day E-commerce SEO Strategy
aleyda
25
6.7k
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
Вопросы