Эргономичный код
796 subscribers
76 photos
3 videos
20 files
384 links
Канал о разработке поддерживаемых бакэндов - про классическую школу TDD, прагматичное функциональное программирование и архитектуру и немного DDD.

Группа: https://t.me/+QJRqaHI8YD

https://azhidkov.pro
Download Telegram
Привет!

Внезапный "а знаете ли вы пост?".

Наверняка вы слышали, что при проектировании REST API необходимо отдавать предпочтение стандартизированный штукам, например для авторизации использовать заголовок Authentication.

Чего вы, возможно, не слышали (по крайней мере я не слышал до вчерашнего дня) - ответы на запросы с заголовком Authentication запрещено кэшировать по умолчанию. А если использовать доморошенные заголовки, то надо не забыть явно запретить кэширование ответов.

#http_api@ergonomic_code #rest_api@ergonomic_code #posts@ergonomic_code
Привет

Сегодня у нас рубрика "Мои факапы".

Есть у меня один проект, где флоу создания одной из сущностей такой:
1) непривилегированный пользователь создаёт сущность
2) привилегированный пользователь её одобряет или отклоняет

ну и плюс привилегированный пользователь может её редактировать в любой момент.

я уже подробностей дизайна не помню, но с одной стороны у меня вроде были какие-то трудности с проектированием урла для аппрува (хотя щяс ретроспективно не понимаю, что за трудности), а с другой стороны чёт захотелось поэкономить методы.

В итоге сейчас у нас есть метод PATCH /entity/{id}
который принимает сущность с 15 нуллабельными полями. используется двумя способами - либо присылаются все 15, либо 1 - approved

И есть метод POST /entity
С теми же 15 полями. но не нуллабельными.

И хз что с этим добром теперь делать.

Щяс я уже думаю, что надо было не выпендриваться, обновление делать через PUT, а аппрув через PATCH /entity/{id}/approved или POST /entity/{id}/(approve|reject)

А от PATCH-а сущностей держаться подальше до тех пор, пока требования к стенке не припрут - в языках со статической типизацией это боль

И заодно наткнулся на прикольную штуку JSON-P - когда мне придётся в следующий раз делать патч, я так пойду, а не через типизированную нуллабельную ДТОшку

#case@ergonomic_code #project_camp@ergonomic_code #http_api@ergonomic_code #rest_api@ergonomic_code #tools@ergonomic_code
Привет!

Зацените чё накапал я ненавижу и работать с АПИ в виде сваггера (оно почти всегда не работает полностью) и уш тем более писать его - пихать в код гору аннотаций для доков к сваггеру, где соотношение сигнал шут 1 к 2 - то ещё удовольствие.

И сам я предпочитаю писать доки на Spring Rest Docs - и собственно текст доков можно нормально писать, и примеры гарантированно рабочие. Но многие привыкли таки к сваггеру и хотят его. А с этим тулом, кажется, можно разом обоих зайцев убить.

#docs@ergonomic_code #spring@ergonomic_code #http_api@ergonomic_code #rest_api@ergonomic_code
👍3
Привет!

Я тут вынашиваю страшный план - отказаться от REST-стиля в "бэке одного фронта".

Как я собираюсь это делать:
1) Ядро продолжать так же делать из подсистем-объектов
2) Вокруг ядра сделать слой app, где по конторллеру на каждую страницу/экран/вью
3) урлы будут вида /api/app/login-page/login, api/app/dashboard-page/get-init-data
В общем в некотором смысле вернуться к структуре из этого поста, но сервисы приложения смёржить с контроллерами. Ну либо к пакетированию по компонентам Брауна

Что надеюсь получить:
1) Упростить процесс проектирования. Я давно этим занимаюсь и прочитал пачку книг по РЕСТу, но всё равно буквально в каждом проекте вылазит какая-нибудь штука, над которой я долго грею голову
2) снизить сцепленность ядра. в моём текущем подходе зачастую в подсистему надо тащить зависимость на другую подсистему, только для того чтобы вытащить вложенную сущность для какой-нить админки
3) Повысить удобство для фронтендеров - у них постоянно возникают вопросы что откуда брать для данной конкретной страницы. Тут, надеюсь, не будет. Плюс в доках появится понятное место куда можно будет сиквенс диаграммы работы страницы воткнуть
4) Повысить производительность. Как засунуть в рест один запрос для формы ввода, который вернёт пачку справочников для выпадающего списка - я не очень понимаю. А в эту схему - очень понимаю

Что потеряю и как планирую нивелировать потери
1) идиоматичность. С РЕСТом в целом народ как-то уже разобрался, а тут опять какая-то непонятная хрень. Это я попробую нивелировать за счёт простоты, возможности перенести общие принципы проектирования и постами с описанием идеи и кейсов
2) универсальность. Новому клиенту может не подойти существующее АПИ. Для второго клиента можно будет завести свой набор методов, а для третьего уже спроектировать и прикрутить сверху REST апи

Пока не очень понимаю что делать с методами, которые нужны на разных страницах. Но есть несколько идей:
1) по факту дублировать эндпоинты для них с минимизацией дублирования кода через делегирование в Котлине (и кстати о Котлине - я последнее время работаю с .net и чёт прям устал от NullPointerException - хочу назад в налло-безопстность 😥)
2) оставить такие методы в ядре
3) завести понятие ui-компонента на бэке - урлы вида /api/app/image-component/load

Я пока ещё думаю на эту тему и не уверен, что пойду туда, но возможно в ближайшем времени опробую её на личном проекте. И если опробую - расскажу как впечатления:)

#http_api@ergonomic_code #rest_api@ergonomic_code #ergo_approach@ergonomic_code
👍1
Привет!

Я ещё почти два года назад назад начал думать в сторону того, что пути эндпоинтов REST/JSON-over-HTTP API надо нарезать исходя из UX-клиентов, а не сущностей/ресурсов.

То есть, допустим, у нас есть пользователи и три эндпоинта:
1. Залогиниться
2. Посмотреть собвтенные данные
3. Посмотреть данные любого юзера для админов

И раньше я делал сам и наблюдал буквально во всех проектах, которые видел, эти эндпоинты замапили бы на:
1. POST /users/login
2. GET /users/profile
3. GET /users/profiles/{id}

А сейчас я бы это зампаил так:
1. POST /public/login
2. GET /user/profile
3. GET /admin/profiles/{id}

И после того, как я отказался от объектно-ориентированной декомпозиции и актуализировался вопрос декомпозции слоя приложения - эта идея заиграла новыми красками - первичную декомпозицию слоя приложения можно делать по UX-ам - считай приложениям

И, например, в TA я это так и сделал - если не считать вспомогательных пакетов infra и platform, в пакте app два подпакета:

1. public - "приложение"-точка входа, для регистрации и логина (по историческим причинам мапится на "/"...)
2. therapist - "приложение"-АРМ терапевта (мапится на "/therapist/")

Ещё есть "приложение"-сисадмина - Spring Boot Actuator (мапится на "/ops/**")

Такая схема, среди прочего ещё и существенно упрощает конфигурацию авторизации

Но это всё была прелюдия.

Я тут наткнулся на оригинальный пост про гексагональную архитектуру (ака порты и адаптеры), а там:
What exactly a port is and isn’t is largely a matter of taste. At the one extreme, every use case could be given its own port, producing hundreds of ports for many applications. Alternatively, one could imagine merging all primary ports and all secondary ports so there are only two ports, a left side and a right side.


Neither extreme appears optimal.


The weather system described in the Known Uses has four natural ports: the weather feed, the administrator, the notified subscribers, the subscriber database. A coffee machine controller has four natural ports: the user, the database containing the recipes and prices, the dispensers, and the coin box. A hospital medication system might have three: one for the nurse, one for the prescription database, and one for the computer-controller medication dispensers.


It doesn’t appear that there is any particular damage in choosing the “wrong” number of ports, so that remains a matter of intuition. My selection tends to favor a small number, two, three or four ports, as described above and in the Known Uses.



Что именно является портом, а что нет, во многом является делом вкуса. С одной стороны, каждому юз-кейсу можно было бы присвоить свой собственный порт, создав сотни портов для множества приложений. В качестве альтернативы, можно было бы объединить все основные и все дополнительные порты, чтобы было только два порта, левый и правый.


Ни один из крайних вариантов не кажется оптимальным.


Система прогнозирования погоды, описанная в "Известных вариантах использования", имеет четыре естественных порта: канал прогноза погоды, администратор, уведомленные подписчики, база данных подписчиков. Контроллер кофемашины имеет четыре естественных порта: пользователь, база данных, содержащая рецепты и цены, дозаторы и ящик для монет. Больничная система выдачи лекарств может состоять из трех компонентов: один для медсестры, один для базы данных рецептов и один для диспенсеров лекарств с компьютерным управлением.


Похоже, что выбор “неправильного” количества портов не может нанести какой-то особый ущерб, так что это остается вопросом интуиции. Мой выбор, как правило, делается в пользу небольшого количества - двух, трех или четырех портов, как описано выше, и в известных случаях использования.


И я в этом тексте вижу те же самые приложения (в "левых"/основных портах у Кокбёрна), что и у себя.

В общем советую подумать в сторону того, сколько UX-ов есть у ваших (монолитных) бакендов и отражено ли это в вашей архитектуре

#design@ergonomic_code #rest_api@ergonomic_code #hexagonal_architecture@ergonomic_code #trainer_advisor@ergonomic_code
🔥43👍2