Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Что не так с REST
Search
Deep Refactoring
August 31, 2017
Education
0
200
Что не так с REST
Иван Гришаев
Deep Refactoring
August 31, 2017
Tweet
Share
More Decks by Deep Refactoring
See All by Deep Refactoring
Поворот на 90°
deeprefactoring
0
130
Card Payments 101
deeprefactoring
0
130
Звонки на стероидах
deeprefactoring
0
110
Make Time
deeprefactoring
0
85
Learn-to-Rank или как научить бездушную машину хорошо искать
deeprefactoring
0
180
Уменьшаем количество рефлексии в коде
deeprefactoring
1
83
Прикладная кодогенерация для Java разработчика
deeprefactoring
0
420
Пишем игровой навык для Алисы Яндекс с помощью Excel
deeprefactoring
0
180
Подружиться с исключениями. Иван Гришаев, Exoscale
deeprefactoring
0
180
Other Decks in Education
See All in Education
Node-REDで広がるプログラミング教育の可能性
ueponx
1
210
子どもが自立した学習者となるデジタルの活用について
naokikato
PRO
0
160
SJRC 2526
cbtlibrary
0
160
1014
cbtlibrary
0
500
相互コミュニケーションの難しさ
masakiokuda
0
320
【dip】「なりたい自分」に近づくための、「自分と向き合う」小さな振り返り
dip_tech
PRO
0
190
Evaluation Methods - Lecture 6 - Human-Computer Interaction (1023841ANR)
signer
PRO
0
1.2k
いわゆる「ふつう」のキャリアを歩んだ人の割合(若者向け)
hysmrk
0
260
Google Gemini (Gem) の育成方法
mickey_kubo
2
730
多様なメンター、多様な基準
yasulab
5
19k
ThingLink
matleenalaakso
28
4.2k
RGBでも蛍光を!? / RayTracingCamp11
kugimasa
1
260
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
Agile that works and the tools we love
rasmusluckow
331
21k
The Invisible Side of Design
smashingmag
302
51k
Designing Experiences People Love
moore
143
24k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Optimizing for Happiness
mojombo
379
70k
Building Applications with DynamoDB
mza
96
6.8k
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
Вопросы