Друзья, не думал, что тема еще актуальна в 2021 г., темболее на рубеже 2022.
Начало битвы за фронтенд
Все началось с того, что я задал вопрос «Как передать на бекенд требования к API?» в Хабр вопросах с гипотезой (сразу прошу прощения за профессиональный жаргон):
Если фронты хорошо знают REST, то это реальный профит, когда они сами могут накидать в Swagger ендпойнтов, которые потом утвердит или поправит бекенд. Если добавить сюда удобный редактор в стиле Notion - когда тут же правим и видим превью ендпойнта. А если, еще к нему зацепить Swagger с реализованного бэка потом, и эта штука сделает кросс-валидацию и скажет, где контракт нарушен – то вообще огонь или нет?
И вот, что из этого получилось:
@Vitsliputsli Многие фронтендеры относятся к беку, как к некой обертке для работы с базой данной. Когда такие становится лидом команды и начинают диктовать свои требования беку, начинается ад, проект даже с простым беком превращается в нечто монструозное, разваливающиеся на ходу. Судя по вашим фразам, вы скорее всего один из них.
@AgentSmith Совсем спустился до личных оскорблений и писал про фронтов как про обезьянок. К сожалению, (или счастью) ему стало стыдно и он удалил всю свою ветку, где писал оскорбления. Оставив только вот это:
@AgentSmith Судя по вопросу ты некомпетентен и лидом ты назвал себя сам. Подтвердить свою компетенцию на должность лида ты не можешь.
Из группы Боль Тим Лида в телеграм:
Да я бы даже сказал, что это бредово. Фронты это же обезьяны умеющие только делать запросы и выводить их. Им то д****ды как там все устроено на сервере. Пускать фронт к проектированию API это плохая идея, напроектируют. Еще бы фронт мне диктовал как реализовать API.
Если полистать комментарии, явно чувствуется крайне негативная повестка от вопроса. Я старался быть максимально вежливым, при этом часть собеседников явно не сдерживали эмоций. Это лишь небольшая часть «токсичности» вылитая на фронтов и лично меня. За фронтов обидно :-)
Хотя я @breslavsky старался и приводил множество аргументов:
@breslavsky Мне кажется проблема в том, что некоторые бекенд разработчики, неверно понимают разработку бизнес-логики и разработку интерфейса доступа к ней и к данным. Интерфейс на бекенд может быть HTTP, сокеты ли даже командная строка. Это всего лишь интерфейс. Эти разработчики при проектировании ендпойнта
/login
часто зашивают в контроллер бизнес-логику, работу с базой, генерацию сессии и т.д. И именно поэтому они связывают проектирование API с разработкой кода функции и именно поэтому когда им нужно добавить, например, GraphQL им нужно дублировать код.
@breslavsky Почему заранее нельзя договориться с фронтом как данные будут бегать туда-обратно и начать работу параллельно? Такого кейса нет? Фронты не могут предложить вариант, как это видят? Вы на беке дадите добро или внесете изменения и у вас будет контракт с фронтами. Вы спокойно пойдете делать и они тоже. Потом через какое-то время вы соединитесь и проверите, что ваш контракт выполнен. Что тут не так?
Spec-First Development
Я понял, что многие просто не знают про подход – Spec-First Development.
Spec-First – это философия о том, как разрабатывать API более эффективно. Если вы следуете философии «сначала спецификация», вы сначала пишете спецификацию и используете ее в качестве контракта, к которому разработчики пишут код.
Многие думают, что Swagger (Open API) – это «UI шкурка», которую генерирует в конечном счете бек из кода, они не понимают, что это в первую очередь – JSON схема описания API.
Взято из https://starkovden.github.io/introduction-openapi-and-swagger.html
Можно сгенерировать свою спецификацию из аннотаций кода, но говорят, что автоматическая генерация - не лучший подход. Майкл Стоу (Michael Stowe) в статье Беспрепятственный REST: руководство по проектированию Perfect API рекомендует группам вручную реализовать спецификацию, а затем обрабатывать документ спецификации как документ, который разработчики используют при выполнении реального кодирования. Этот подход часто упоминается как «spec-first development».
Ну и инструмент для создания API спецификаций https://swagger.io/tools/swaggerhub/
Более 15 000 команд разработчиков программного обеспечения по всему миру используют SwaggerHub. Поскольку спецификация OpenAPI становится в большей степени отраслевым стандартом для документации API, специфичные инструменты SwaggerHub имеют важное значение.
Видимо, ни одного из этих 15 000 в комментариях не оказалось.
Фронты могут проектировать API
Мы в команде давно используем Swagger, мы пишем его заранее на фронте, потом передаем на бэк, что бы они реализовали, что нам нужно. И да, мы не обезьянки, мы понимаем, что такое REST, пейджинг, сериализация и т.д. Мы согласовываем API с беком, вносим правки вместе, и работаем параллельно - это правда удобно. Конечно бизнес-логика отдельный вопрос – это чистый бэк, туда мы не лезем.
Нам не совсем удобно работать с одним большим Swagger YAML файлом, а так же при проектировании ендпойнтов и схем данных не хватает привязки в пользовательскому интерфейсу приложения, что бы понимать, какие экраны (фичи) уже покрыты API, а какие нет.
Мы всегда ищем способы улучшения наших процессов и мой вопрос, по сути был элементом «кастева», что бы предложить одно из возможных решений, которые мы планировали разработать.
И спустя пару месяцев мы разработали – API Projector ↗
Визуальный Swagger редактор
API projector – это визуальный Swagger редактор с возможностями привязки API к пользовательскому интерфейсу системы (приложения).
В нем, фронтенд разработчики, могут опираясь на UI (с пользовательской историей) спроектировать API, отправить его на проверку бекенду, согласовать и утвердить, а потом после реализации проверить, что все контракты выполнены.
Бекенд экономит время для концентрации на бизнес-логике, фронтенд предлагает формат взаимодействия с бизнес-логикой операясь на потребности пользовательского интерфейса.
Покажу несколько примеров как это работает вместо длинного описания.
Ну и другие киллер-фичи на будущее:
Более удобное обсуждение контрактов через внутренние чаты.
Валидация спеки с реальными серверами, например:
dev
,rc
,prod
. Всегда знаем какие отличия есть в ендпойнтах и схеме данных.Автоматическое тестирование ендпойнтов реального сервера на «уничтожение» через Schemathesis ↗
Спасибо друзья, очень нужна Ваша обратная связь: как считаете будущее за Spec-First Development или полный Agile (шутка): митинги, JSON-чики в чатиках и т.д.?
Комментарии (233)
VadimChin
02.01.2022 18:24+20Субъективно. Отвественный должен быть один, назвать его можно как угодно, архитектор, фулстек, сеньер-помидор. Негатив понятен, сам видел как фронты прибивали крупные проекты, когда не погружались в архитектуру, а просто ендпоинты удобные и красивые делали. Это из разряда - у меня есть прекрасная идея, но отвественность за результат на тебе.
danial72
02.01.2022 21:17+8Мне кажется, что фронтенд не должен проектировать api. Фронтенд должен очень четко описать, что он хочет получить в api. А бэкендер должен очень ответственно и честно объяснить почему лучше сделать по другому.
Ilusha
02.01.2022 21:28+5Собственно, Вы кратко выразили содержание поста: совместное проектирование.
breslavsky Автор
04.01.2022 01:15Спасибо за поддержку, именно это я и хотел донести для тех кто прочитает статью полностью.
Ilusha
02.01.2022 22:12+5В вашем примере меня удивляет квалификация бэка: почему они не спорили? Не выдвигали аргументы?
Ответственность за API всегда должна быть на бэке, но нет никаких проблем построить процессы так, что наброски контрактов готовятся фронтами (которые, в свою очередь определяет ux), а дальше уже валидируются бэками. А ещё можно сразу обсуждать вместе: ux, front, middleware|back, PO. Я и с таким процессом работал.
-
Как фронт, скажу: мне вот нафиг надо делать ещё и работу по проектированию api. Но - надо, бэк не погружается в ux так же как я, у него своей работы море. Поэтому - совместная работа, с уважением к работе друга: фронты - это не формошлепы, а бэки|middleware не crud-ошлепы.
breslavsky Автор
04.01.2022 01:16А как же тогда сказать бэку, что вам от него нужно? Чаты? JSON-чики?
Ilusha
04.01.2022 03:14+1Бэк же не сидит в вакууме, он должен знать свой продукт. Почти везде, где я работал, бэк знал, что мне нужно: мы же оперируем одними и теми же сущностями, просто с разных сторон.
Или задачи были простыми, что обсуждение не требовалось, или обсуждали голосом, или обсуждение продуктовой задачи велось совместно со всеми участками. Иногда бэк готовит draft-контракт, а фронт валидирует. А иногда - наоборот. Иногда структуру данных диктует аналитик. В общем, много разных вариантов процессов. Ещё есть вариант, когда бэк, который даёт API - это лишь часть системы. И тогда запрос фронтов на данные - это лишь пожелание.
Neikist
02.01.2022 18:26+16Фронты могут проектировать API
Как мобильный разработчик, ранее затрагивавший БД и бек — кмк, лучше бы фронты не брались действительно за проектирование апи, если у них нет знания кодовой базы бека и бд. Ну либо апи разрабатывалось бы совместно. Ибо без знания какие там индексы, какие субд используются подо что, какие запросы сейчас для бека тяжелые а какие нет — можно дел наворотить.Ilusha
02.01.2022 21:32+2Только в посте об этом и написано: совместно.
Просто риторика поста должна была быть более чёткой: фронты могут (должны?) принимать участие в проектировании API.
В довольно сумбурной подаче может показаться, что посыл в том, что только фронты должны проектировать.
Neikist
02.01.2022 21:43+1А мне кажется автор именно и настаивает в этой статье что фронт первичен, а бек должен молча внимать и только принимать спеки на реализацию.
Ilusha
02.01.2022 22:20Мы согласовываем API с беком, вносим правки вместе, и работаем параллельно - это правда удобно. Конечно бизнес-логика отдельный вопрос – это чистый бэк, туда мы не лезем.
Там еще по тексту есть еще отсылки к совместной работе и улучшению процесса.
Здесь речь описывается уже рабочий процесс, который принят в команде, а не топание ножкой "я не обезьянка".
Вообще, кмк, мы тут видим что-то похожее на DDD
breslavsky Автор
04.01.2022 01:17Это не так, вся статья пронизана, что фронты-вносят предложения, а бэк согласовывает.
mentin
03.01.2022 05:40+4Да, там есть по совместную работу, но в конце суммируется видение:
фронтенд предлагает формат взаимодействия с бизнес-логикой операясь на потребности пользовательского интерфейса.
То есть они API похоже проектируют под каждый нарисованный экран, и по тексту видно - после рисования UI элементов. Да, бэкенд участвует, но создаётся все для конкретной ситуации на фронтенде.
Это кошмар, это обычно приводит к созданию отдельных API под каждый экран, тип клиента (десктоп, телефон, планшет) и т.д.
Обычно всё-таки проектируются use cases, выясняется какой API нужен для их поддержки, а не для конкретного экрана. То есть, в терминах автора, опираясь на use cases, а не конкретный UI (который может очень часто меняются).
Хоть автор и пишет "spec first", но у них явно UI first. А надо API first, и проектировать его должен кто-то понимающий и проектирующий use cases, а не под конкретные экраны.
Ilusha
03.01.2022 19:54+1UI, точнее UX, определяет use case.
Визуальное представление здесь важно, чтобы показать всем участникам процесса как будет использоваться API. Это позволяет предусмотреть граничные случаи и обсуждать вопросы предметно: нет человека, который продумывает use case на 100%, есть наброски, которые уже доводятся до ума коллегиально.
По сути они исходят от бизнес-логики на фронте. И здесь вопрос лишь в том, превращают ли они частную ситуацию в общую.
Или вы думаете, что там дураки сидят и не думают о планировании развития?
mentin
04.01.2022 00:50Я не считаю никого дураками, просто так описано - всё после рисования экранов, а не после дизайна use cases. А экраны обычно заметно разные для десктопа, мобильного веба, мобильных приложений, и т.д.
Если бы они написали: у нас продакт менеджеры совмещены с фрондэнд девелоперами, я бы удивился, но бывает. Там же похоже просто продактов нет, есть фронтэнд разработчики кое-как замещающие их функции. Тоже бывает, не считаю никого дураком, но по-моему в большинстве случаев это не самая оптимальная организация труда. Местами может хорошо подходить, но предлагать как здесь как образец для других вряд-ли.
Ilusha
04.01.2022 03:22Что такое use case в вашем понимании?
В моем схема может быть такая, для ситуации в посте:
бизнес даёт требование в виде: нам нужно сделать страницу с аналитикой по каждому пользователю (с кучкой всякой функциональности)
PO формирует feature task, в котором будет draft use case
Задача уходит к ux-специалистку, промышленному дизайнеру, который строит интерфейсы так, чтобы пользователь был доволен: определяет use cases: мобилки, десктоп
фронты готовят draft api, обобщая все в визуальном редакторе - слое абстракции для облегчения взаимодействия с бэком: все можно потрогать и понажимать, а также объясняет без лишних слов, почему нужно именно так.
Бэки валидируют, согласовывают, что-то меняют или полностью рубят.
Если есть проблемы, то организовывается общий митинг с PO для поиска решений
Если нет, то контракт фиксируется. Дизайнеры, бэки и фронты работают параллельно.
Bringoff
03.01.2022 15:41лучше бы фронты не брались действительно за проектирование апи, если у них нет знания кодовой базы бека и бд. Ну либо апи разрабатывалось бы совместно
Право на жизнь имеет скорее только совместное проектирование. Бекендеры ведь тоже не какие-то небожители. На своей практике миллион раз встречался с ситуацией, когда бекенд сделан невероятно топорно для использования с фронта, потому что "так было удобнее". А то, что вместо одного запроса надо отправить три 3, соответсвенно, ошибки каждого требуется обработать и как-то вплести во флоу пользователя — это пустяки.
В целом бекенд должен быть готов на большее количество уступок. Потому что задеплоить какое-то изменение или фикс на бекенд намного быстрее, чем на клиент, если клиентов несколько либо это не веб-фронтенд.
nin-jin
04.01.2022 13:24А то, что вместо одного запроса надо отправить три 3, соответсвенно, ошибки каждого требуется обработать и как-то вплести во флоу пользователя — это пустяки.
Заем вы обрабатываете ошибки каждого запроса по отдельности? Напишите уже обобщённый код.
Bringoff
04.01.2022 13:26Заем вы обрабатываете ошибки каждого запроса по отдельности?
За тем, что для разных ошибок требуется разная обработка, в зависимости от контекста.
И тут дело не только в обобщенном коде. 3 запроса с клиента — это менее стабильно, сеть может пропасть между запросами, надо решать вопросы, например, консистенции из-за этого.
nin-jin
04.01.2022 15:32Чего это для одинарного запроса вам разная обработка не нужна, а для тройного вдруг потребовалась?
Ну да, а ещё 3 запроса можно запускать параллельно да ещё и к разным серверам и по разному кешировать.
Bringoff
04.01.2022 15:50Чего это для одинарного запроса вам разная обработка не нужна, а для тройного вдруг потребовалась?
Ну, представим ситуацию. Она почти выдуманная (похожее в моей практике было). В мобильном приложении пользователь создает каким-то образом сущности "магазин", "отдел", "полка", которые, конечно же, связаны между собой. Упертый бекенд хочет строго следовать json api и требует отправлять эти сущности тремя разными post-запросами. Как я писал выше, потому что бекенду "так удобнее". Каждый запрос отправляет свои поля, поэтому ошибки валидации могут быть разные.
Также надо решать вопрос, что один запрос успешен, а 2 зафейлились. Либо это на клиенте трекать, и отсылать только зафейлившиеся запросы, что добавляет оверхеда в логике клиента. Либо делать ретрай всех полей сразу, что привносит оверхед на использование трафика пользователя, возникает больше точек соприкосновения с идемпотентностью бекенда.
ещё 3 запроса можно запускать параллельно да ещё и к разным серверам и по разному кешировать
Если надо 3 запроса к 3 разным серверам, то это будет 3 запроса. Но мы сейчас говорим немножко не об этом. И опять же если у нас клиент ходит в 3 разных места, то чаще всего мы что-то делаем не так. Логику похода в разные места на бекенд закинуть опять же проще, а не раскрывать такие знания клиенту.
nin-jin
04.01.2022 16:14Ошибки валидации просто мёржатся и обрабатываются единоообразно. Ну а если запросы к серверу неидемпотентны, то проблемы будут что с 1, что с 3 запросами. А если идемпотентны, то проблем не будет и так и так.
Поход в разные места - это, например, авторизация на сервере авторизации, получение справочников из cdn и создание профиля на конкретном сервисе.
Bringoff
04.01.2022 16:35проблемы будут что с 1, что с 3 запросами
Проблемы разного уровня. Если после одного запроса пропадает сеть и 2 других не доходят, незаконченная сущность будет болтаться на бекенде неопределенное количество времени. Мне что-то кажется, вы не делали мобильных приложений :)
авторизация на сервере авторизации, получение справочников из cdn и создание профиля на конкретном сервисе
Это три разные вещи, непонятно, почему мы о них говорим.
nin-jin
04.01.2022 16:39Если бэкенд выдал такое апи, значит он должен быть готов к такому развитию событий. В любом случае клиенту-то всё равно.
А для пользователя это одна вещь - форма регистрации в сервисе.
mayorovp
02.01.2022 18:36+18И да, мы не обезьянки, мы понимаем, что такое REST, пейджинг, сериализация и т.д.
Иронично, что вы перечислили как раз те стороны API, которые не играют никакой роли. Настоящая боль плохого API — в изменяющих запросах.
Допустим, у вас есть сущность foo в коллекции foos, и вам хочется её создать. Казалось бы, логично это делать через POST либо PUT на какой-нибудь URL /foos/create или там /foos/new? Но как только вы включаете такую конечную точку в ваш API — вы тем самым постулируете, что сущность foo является самостоятельной сущностью, и может быть создана в отрыве от остальных. А это совершенно не всегда так. Возможно, что сама возможность создать foo и какой-нибудь bar не парой, а по-отдельности, уже является дырой в безопасности.
Впрочем, бывает и наоборот. Когда за проектирование БД берутся какие-нибудь бизнес-аналитики, они всегда забывают о праве пользователя сделать перерыв при заполнении формы на пару дней — а потом эти требования неизбежно и в API перекочёвывают; так что желание фронтов на процесс проектирования API хоть как-то влиять вполне понятно.
youzless
04.01.2022 01:20"Казалось бы, логично это делать через POST либо PUT"
что за бред. /foos сам по себе должен являтся ресурсом. GET - view data, POST - create, PUT-update. DELETE - соответственно.
Связь сущьностей foo и bar API не регламинтирует. просто POST /foos шлет лесом запрос в котором отсутствует в data внешний ключ, передовая соответсвующий http status...
mayorovp
04.01.2022 11:22что за бред. /foos сам по себе должен являтся ресурсом
Это всего лишь одно из соглашений, и в данном случае ваше предложение ничего не меняет.
просто POST /foos шлет лесом запрос в котором отсутствует в data внешний ключ
Тем самым постулируется возможность создать сначала bar, а потом создать (или не создать) foo. Но что делать если они могут быть созданы только парой?
int03e
04.01.2022 11:35Но что делать если они могут быть созданы только парой?
Как вариант — вводится понятие какого-то FooBarEntity, и потом POST /foobars.mayorovp
04.01.2022 12:11Ну да, разумеется как-то так сделать и надо. Но известно ли это фронтендерам, что требования безопасности не разрешают создавать эти сущности иначе как парами?
int03e
04.01.2022 12:39Это, по идее, на груминг митинге должно выясняться, но я согласен — лучше, если API проектируется на бекенде и потом дорабатывается с учетом пожеланий фронтов, а не наоборот.
Sano000
02.01.2022 18:40+3Отличный пример как можно разосраться в команде еще на стадии проектирования, а через 5 месяцев когда продукт будет разваливаться - сказать "это все потому что вы ничего не понимаете".
Так то подобные вещи нужно обсудить внутри команды, если будет одобрение - тогда вперед. Если нет - ну можно попробовать в следующем проекте предложить.
Таких "хороших практик" десятки и сотни, но надо их не насаживать своим дутым авторитетом, а доказать примером что они полезны.
JustDont
02.01.2022 18:42+2Честно говоря не понял насчет "проектирования API". Как это всё должно выглядеть и пролезать в транспорт? Это да, тут участие фронта очень часто нужно, а то без этого участия то long в JSON попробуют положить числом, то справочные данные выведут не один раз на ответ, а один раз на каждую из 10000 строк таблицы.
А вот в вопросы "как это всё будет работать" я с фронта и не собираюсь лезть. Тут бэкам сильно виднее, где у них будут узкие места, и как сквозь них всё должно пролезать.
jMas
02.01.2022 18:44+2Проблемы конечно на уровне согласования контрактов есть, безусловно, но чаще видел что архитектура строится криво (неправильныо наполненные сущности или лишние слои для гибкости которая в некоторых местах не нужна, уехавшая в другие места ответственность). Лечить апи безусловно можно и нужно - все что помогает взаимодействию - это хорошо, но все же это похоже на лечение симптомов (исключительно мое мнение). Спасибо за пост!
Ilusha
02.01.2022 22:55+1А я вижу в этом подходе нечто похожее на предметно-ориентированное программирование.
jMas
03.01.2022 00:01+1Поддерживаю, есть слой где сущности и бизнес-правила живут независимо от окружения. И тогда создавать слои-интерфейсы доступа (API) поверх - можно сколько угодно. Единственное здесь - абстракции имеют свою цену, которая не отбивается на маленьком масштабе (там да, лучше "как получится").
Ilusha
03.01.2022 00:36Малый масштаб - Вы про размеры задач? Думаю, тут вопрос конкретных процессов.
Если каждый раз нужно в этот слой ручками добавлять, например, справочник, после чего его прописывать в другом API, и не одном, то выглядит это оверхедом.
А вот если эта визуальная среда синхронизирована с реализацией бэка, то на небольших в проектировании задачах гораздо легче накидать на бэке, после чего уже получить аппрув от фронта. Очень часто обсуждение API словами - 2-5 минут живого общения или несколько сообщений в мессенджере.
В общем, это один из возможных инструментов, который кому-то подойдёт, а кому-то нет.
jMas
03.01.2022 00:42Я про масштаб проекта. Вкратце:
Часто для экономии ресурсов (времени и денег) код, берущий и трансформирующий данные из базы, пишется сразу в функции, которая их должна вернуть фронту (прям буквально все без разбиения: запрос в базу, перебор данных и трансформация, склеивание с данными из другого запроса, формирование JSON-ответа). И это тоже не плохой вариант, если требования снаружи минимальны, API не должен эволюционировать, и затраты на архитектуру не окупятся в перспективе. Как пример: какой ни будь промо-сайт с убер-фичей (показать рейтинги в режиме реального времени) для единичного заказчика под ключ (утрировано).
Интересная мысль возникла по поводу:
В общем, это один из возможных инструментов, который кому-то подойдёт, а кому-то нет.
Нас везде учат, что нужно все разделять, писать красиво. Создается табу на написание плохого кода (без разбиения на слои, например). И разработчики могут попадать в эту ловушку, потому что: существует стереотип что необходимо писать обязательно гибкий код (так пишут во всех книжках); разработчик не видит задачу целиком (поэтому не может выбрать стратегию - писать "на коленке" или "по-взрослому"); мы не знаем что потребуется завтра (увы, но иногда легче выкинуть и написать с нуля "по-взрослому", но не все готовы выбросить кучу написанного на коленке кода).
micbal
02.01.2022 18:55+4Беда, коль пироги начнет печи сапожник,
А сапоги тачать пирожник,
И дело не пойдет на лад.
Да и примечено стократ,
Что кто за ремесло чужое браться любит,
Тот завсегда других упрямей и вздорней:
Он лучше дело всё погубит,
И рад скорей
Посмешищем стать света,
Чем у честных и знающих людей
Спросить иль выслушать разумного совета.
Так как бэкам понятнее нормализация данных в базах, ядро бизнес логики, связи микро сервисов и т.п., и это все по сути ядро всего софта, то выглядит логичным если проектирование исходит от бэков.
tzlom
02.01.2022 19:38+5Угу, а потом прохладные истории о том как бэк переименовал и перетасовал поля в API потому что у него видение БД сменилось а фронт 2 недели ползал по коду чтобы эти переименования правильно заселить.
Работаете вместе ну так работайте вместе, и над API тоже
micbal
02.01.2022 19:47+2Если в вашем примере бэк следовал задачам бизнеса, то это нормальная история, но предоставить полную информацию фронту заранее и с обоснованием конечно было нужно. Есть у меня обратная история, SEO и бизнес потребовали большого ускорение отдачи данных, пришлось мигрировать одну базу на две с последующими изменениями. Частично поменялись точки реста. Я понимаю боль фронта, но как иначе?
awfun
02.01.2022 23:19+1Иначе - когда фронтом является мобильное приложение, и требуется поддерживать старые версии, пока все клиенты не мигрируют на актуальную
noodles
03.01.2022 12:52бэк переименовал и перетасовал поля в API потому что у него видение БД сменилось а фронт 2 недели ползал по коду чтобы эти переименования правильно заселить
Частично поменялись точки реста. Я понимаю боль фронта, но как иначе?Можно недоверять бекенду и валидировать апи-респонс на таком же уровне паранои, как и пользовательский ввод. Да, валидировать руками в коде (не так тяжело и страшно, как может показаться).
Т.к. по настоящему доверять мы (фронты) можем только своему написанному коду, а не "сваггерам" или "автоматически сгенерированным клиентам", правдивость которых на самом деле тоже зависит от человека.
Как только респонс не соответствует принятому контракту - прерывание работы приложения и запись в лог, что именно не так. В итоге - находится и поправляется всё очень быстро (особенно если код на TS).
Особенно удобно когда команда распределённая, бек пишут пять разных команд из разных кантор в разных частях мира, и общение с беком только(!) через прослойку в виде других людей.micbal
03.01.2022 12:58Если бизнес устраивает двойная валидация, и проброс ошибок в обоих направлениях, то это отличный вариант.
Neikist
03.01.2022 15:29Т.к. по настоящему доверять мы (фронты) можем только своему написанному коду
Да тоже не особо выйдет, в код можно и вмешаться. Как в веб странички, так и в нативный.
kalombo
02.01.2022 21:47+4Для этого создаётся новая версия апи и постепенно всех переводят на него. Апи могут ещё и другие сервисы(бэки) пользоваться из других команд. Вот так все резко поменять, все поломав - это некомпетентность вашего бэка, не в коллаборации с фронтом дело.
amarao
02.01.2022 20:17+2Как часто меняется определение сапога? Если "сапог" уже депрекейтед, а его замена - "лапоть" всё ещё в стадии MVP, то на что полагаться? На сапоги (которые работают, но deprecated), или на лапти, которые многообещающие, но только в форме обещаний, а сейчас ничего не умеют?
Жизнь в IT нельзя передавать через профессии, в которых правнук учится тому же, чему учился прадед.
mentin
03.01.2022 07:06+3API исходя от бэкенда имхо не сильно лучше проектирования начиная с фронтенда. API должны проектировать люди, понимающие в бизнес логике, исходя из наличных use cases, а не деталей реализаций. Безусловно с участием и бекенда и фронтенда, но не начиная ни с того, ни с другого.
Если в API есть создание объекта, то API в первую очередь должен определяться тем, кто, в каких условиях, может его создать, какие данные нужны для создания. Потом бэкендщики могут добавить что-то скажем для атомарности, а фронтендщики опции для уменьшения числа round trips, но ни те ни другие не должны быть основой для API.
mayorovp
02.01.2022 18:58Кстати о сваггере и прочих OpenAPI. Лично мне они не нравятся тем, что сводят весь REST к RPC. Не то чтобы это было плохо — в конце концов, RPC не просто так стало популярной штукой, но остаётся какое-то чувство некрасивости.
Вот я делаю конечную точку для импорта данных в коллекцию, с маршрутом вида /api/{collection}/{version}/import. Именно в таком порядке — ведь я позаботился (пусть меня и не просили) чтобы по пути /api/{collection} можно было увидеть список версий, а по пути /api/{collection}/{version} — список всех возможных операций и их доступность для текущего пользователя; и таким образом получается красивая естественная вложенность ресурсов.
А потом эта конечная точка попадает в OpenAPI под именем ImportDataToCollectionVersion, под тем же именем она попадает в автоматически сгенерированный клиент, и вообще никто не видит итогового URL. С тем же успехом я мог сделать конечную точку /api/import?collection={collection}&version={version}, и ничего бы не изменилось для системы в целом.
NetBUG
02.01.2022 19:31При наличии возможности однозначного преобразования URI (из красивого пути со слешами в путь с параметрами и наоборот, как, например, лет 10-15 назад массово делали для проектов на PHP + Apache mod-rewrite) это вообще несущественная деталь. Выше уже сказали, что API, в первую очередь, это про определение набора сущностей, с которыми можно взаимодействовать, и способ взаимодействия (просмотр, изменение, удаление). И эту задачу обычно решает архитектор, видя все ограничения на стадии проектирования.
Про RPC я не очень понял, это механизм, лежащий ниже уровнем в абстракции, как мне кажется.
mayorovp
02.01.2022 19:43+2REST — оно как раз про структуру URL и HTTP-методы
RPC — оно про возможность вызвать функцию, которая выполнится на другом хостеПри использовании генератора клиента на основе OpenAPI и любого современного серверного фреймворка сетевое взаимодействие происходит так:
- на клиенте вызывается функция, которая делает HTTP-запрос;
- на сервере этот запрос приводит к вызову определённого метода у контроллера.
Это в чистом виде RPC, а весь REST становится всего лишь причудой транспортного слоя.
Выше уже сказали, что API, в первую очередь, это про определение набора сущностей, с которыми можно взаимодействовать, и способ взаимодействия (просмотр, изменение, удаление). И эту задачу обычно решает архитектор, видя все ограничения на стадии проектирования.
И эта задача вообще не имеет никакого отношения к REST. Её как раньше для SOAP решали, как для JSON-RPC решали — так и для REST решают, решения не меняются (разве что REST требует немного более аккуратного решения — и то не всегда).
nin-jin
04.01.2022 13:57REST — оно как раз про структуру URL и HTTP-методы
mayorovp
04.01.2022 16:44-1По вашей ссылке, есть пункт 4.1: Идентификация ресурсов. Это, как минимум, показывает, что URL для REST таки интерес представляет.
А холиварить про то, насколько текущее понимание термина "RESTful" большинством программистов соответствует изначальному мне не интересно — потому что swagger сводит к RPC любую из этих интерпретаций с одинаковым успехом. Не взирая на то, что по вашей же ссылке REST и RPC прямо противопоставляются.
nin-jin
04.01.2022 13:49-1С тем же успехом я мог сделать конечную точку /api/import?collection={collection}&version={version}, и ничего бы не изменилось для системы в целом.
Более того, так и стоит делать изначально. А ещё лучше так:
/api/import?version={versionId}
Иначе получится как с гитхабовским апи, где ты не можешь скачать ишью по айдишнику - изволь протягивать slug пользователя, slug репозитория и порядковый номер issue в репозитории, а при переносе/переименовывании репозитория, изволь обновить все эти slug-и.
mayorovp
04.01.2022 14:01А кто вам сказал, что versionId однозначно задаёт номер версии в отрыве от кода коллекции?
nin-jin
04.01.2022 14:09-1Это суррогатный первичный ключ, он есть всегда, даже если вы о нём не знаете. Что забавно, тот же гитхаб его выдаёт, но что с ним делать - не понятно, ибо запросы требуют slug-и.
mayorovp
04.01.2022 14:32А нахера он нужен в запросе, суррогатный-то ключ? Он же неудобен: становится известен только после деплоя, потенциально различается на проде, стейджинге и в dev-контуре.
В то же время, пара из кода коллекции и номера версии зачастую известна ещё до начала разработки. И вообще весь префикс
"http://{домен}/api/{collection}/{version}/"
в той системе в большинстве бизнес-процессов можно было бы даже хардкодить в строковых литералах, если бы не сваггер.
igrishaev
02.01.2022 19:10+23Если фронты хорошо знают REST
У фронтов принято гордиться тем, что "хорошо" знаешь REST? Что там знать-то, и тем более "хорошо"? Как послать HTTP-запрос? Кажется, все вам правильно сказали.
vsb
03.01.2022 09:58+1Рой Филдинг диссертацию по этой теме написал. Я книжку читал конкретно по этой теме. Если вы считаете, что REST это как послать HTTP запрос, то вы ничего не знаете про REST.
Другой вопрос, что вы в этом не одиноки и правильный REST это редкость. А то, что обычно называют REST — правильней называть JSON RPC over HTTP. Там и впрямь знать много не нужно.
igrishaev
03.01.2022 10:09+1Понятно. Начинается эта гнилая тема: "на самом деле... не то, что вы думаете... вы ничего не понимаете". Если предмет неправильно понимается всеми, значит исходные предпосылки предмета неверны, и коллективный разум поправил его в нужную сторону.
При диссертации и книжки вообще смешно.
siarheiblr
03.01.2022 12:36+5А что смешного? REST это вообще-то архитектурный паттерн и таки да, был темой диссертации. HTTP там вообще не при чем, просто удобно оказалось.
Демонстрировать воинствующее невежество на людях не стоит, все же.
igrishaev
03.01.2022 13:03+3REST -- это гипер-раздутая пустышка, в которой ничего нет. Вдобавок крайне неудобная. Из нее сделали карго-культ. Ничего не умеющие "рок-звезды" решили, что достаточно "выучить REST", чтобы с двух ног влететь в веб-разработку. А в реальности немножечко по-другому.
arthuriantech
03.01.2022 14:17+1REST -- это гипер-раздутая пустышка, в которой ничего нет. Вдобавок крайне неудобная. Из нее сделали карго-культ.
Как-то неправильно этот ваш "коллективный разум" отработал :)
igrishaev
03.01.2022 17:06Наоборот, время все верно расставило по своим местам. Оказалось, что одного лишь "знания REST" недостаточно, чтобы быть хорошим разработчиком. Что без знания других вещей ты все-таки обезьянка, а не разработчик.
arthuriantech
03.01.2022 19:43+1Время всё расставило таким образом, что термин REST стал самым заезженным и бесмысленным баззвордом в бекенд-разработке. Модную приставку RESTful к API припысывает даже последняя собака не зависимо от того каким принципам этот API следует или не слеует.
Выше человек все правильно написал, что исходно REST является архитектурным стилем гипертекстового веба от одного из главных авторов HTTP 1.1, который тот сформулировал в процессе стандартизации протокола. За 20 лет не изменилось ничего - в ядре современного веба работают 6 из 6 огранчений REST. Я не знаю, как так вышло, но с какого-то момента этот термин стали противопоставлять SOAP и затем исказили до CRUD over HTTP, хотя методы HTTP напрямую с CRUD даже не сопоставляются.
Раздутый карго-культ о котором вы писали является порождением этого самого "коллективного разума", который работает как сломанный телефон. Никто не занимает факт-чекингом, ни на что не ссылается, никто не заглядывает в первоисточнки. Зачем, если достаточно прочитать первую нагугленную статью от Krishna Srinivasan?
baldr
02.01.2022 20:17+54Я бэкенд-разработчик. Но когда я выставляю какой-то API - я вижу что он начинает использоваться не так как я планировал, а так как нужно клиенту. И, на мой взгляд, это как раз правильная точка зрения.
Если фронт говорит что для его 10 разных страниц нужно сделать 5 эндпоинтов, которые вытаскивают одни и те же сущности 5 разными способами - я лучше сделаю эти 5 эндпоинтов и оптимизирую их под эти конкретные задачи внутри в коде, чем буду смотреть как вместо одного запроса они вызывают 35 с каждой страницы, потому что "универсальный API и все тут".
Лучше слушать фронтов с самого начала - требования от клиента приходят в первую очередь им. Клиенту неинтересно слушать что у вас там на бэкенде чистый код, DRY/KISS и stateless запросы - он смотрит как быстро страничка загружается и хочет иметь три разных вида корзины, а через месяц захочет четвертый.
Если фронтенд достаточно грамотен чтобы сам написать Swagger-спецификацию - я выйду из дома, сяду в автобус, доеду до его офиса, поднимусь на нужный этаж и поцелую его в сахарные уста. А потом доеду обратно, сяду и напишу бэк, который будет отдавать именно то что нужно, а не то что правильно по REST.
Ilusha
02.01.2022 21:43+6А я с другой стороны, и если ситуацию развернуть: бэк вникнет во все эти клиентские требования, залезет в ux, поймёт, как лучше построить всю архитектуру api без меня и покажет, как классической блондинке из анекдотов, пальчиком спецификацию, то я приеду в офис и расцелую его сахарные уста. И у меня были такие коллеги, это было идеально: мы понимали друг друга с полуслова. Для этого, по сути, нужно отлично знать свой продукт.
Как говорил кот Леопольд: давайте жить дружно. А все эти недовольства из-за плохих процессов, завешенных ожиданий, разного опыта и, положа руку на сердце, завышенном ЧСВ некоторых наших коллег, которые слушают, но не слышат.
baldr
02.01.2022 21:59+1Совершенно верно. Если люди могут договориться - хорошо. Если есть техлид, который сам все разрулит и поставит каждому внятную задачу - очень хорошо.
Как любой, думаю, бэкенд-разработчик, я бы хотел иметь контроль над всем приложением и его производительностью. Чем лучше данные с API удовлетворяют нуждам фронта - тем легче фронт и тем больше контроля у меня. Если фронтенд вынужден использовать только CRUD - он начнет придумывать кэширование у себя, всякие фреймворки и прочую муть, все это разрастается и начинается перетягивание логики.
Если фронт говорит что он знает что ему надо - я только помогу прислать данные в том формате, в котором они нужны ему для отображения.
justmara
02.01.2022 22:52+1Ну это ж как раз вроде нормальный вариант. Было дело - так и работали: система с ноля, вообще ничего ещё нет, только общее представление о бизнес-сущностях и макеты приложения.
1. Прошлись по макетам- стали понятны клиентские выборки. Добавили в список всякие системные (авторизацию, пуши на обновления итд).
2. Прикинули структуру бэка (сущности, взаимосвязи) - стало понятно, какие выборки и чего будут стоить.
Наложили 1 на 2, подрихтовали заведомо неудобные выборки, написали спеку в apiary, отдали аутсорсерам с приложенькой и ушли пилить бэк под эту спеку. Периодически синкались для тестов.Проблемы как раз обычно возникают, когда у фронтов появляется новый красивый удобный/модный экранчик, на котором они разом выводят информацию из охрениарда слабо связанных между собой сущностей и приходят к тебе "а сделай мне метод, который вот это всё за один запрос вернёт?". И хлопают глазками. И что это пол-базы сджойнить надо и с пару десятков смежных сервисов вызвать - им невдомёк.
Дизайнер нарисовал, бизнес утвердил. А то, что это встаёт поперёк архитектуры, построенной ещё год назад по тогдашним требованиям - это уже не их беда. Это вы, на бэке там чот тугие, долго чтоль поправить?Ilusha
03.01.2022 00:47+2В Вашем примере классическая проблема плохого менеджмента. Разрабочики здесь вообще не причём. Раком поставили как фронтов с новым ux, так и бэков, которым теперь нужно много думать.
Вторая проблема: коммуникации. Разработчики вроде друг другу не враги: взяли тряпки, обоссали и пошли стеной на PM/PO.
APXEOLOG
02.01.2022 22:46-1Клиенту неинтересно слушать что у вас там на бэкенде чистый код, DRY/KISS и stateless запросы - он смотрит как быстро страничка загружается и хочет иметь три разных вида корзины, а через месяц захочет четвертый
Прямо с языка снято. А вообще можно посмотреть в сторону GraphQL - он позволяет избежать ситуации с пятью разными, но похожими запросами
nin-jin
04.01.2022 14:23А ситуацию с экспоненциальным дублированием данных при выборке подграфа тоже позволяет избежать? Например, выборка данных друзей друзей, где все являются друзьями друг друга.
jMas
03.01.2022 00:07+1Другими словами - это наличие слоя бизнес-логики (слоя сервисов + БД) и слоя API (контроллеры + трансформеры, которые дергают и склеивают данные из разных сервсов).
siroBS
03.01.2022 18:44+2Хочу поддержать разумное мнение.
Я сейчас пишу фронт и бэк. И когда встал вопрос взаимодействия, пришлось отталкиваться от фронта, потому что фронт крайне необходимо сделать максимально лёгким. Потому что фронт в браузере, потому что фронт не масштабируется, потому что фронт бывает на дохлых древних смартфонах, потому что у фронта, помимо бизес логики, есть UI логика, которая жрёт (прощай React, пробуем Svelte). И чем "тоньше" фронт, тем плавнее и лучше user experience, следовательно, счастливый пользователь - тучный бизнес.
Тут мне могут возразить разработчики фронта как нативного приложения и разработчики, которые расчитывают только на desktop пользователей. Но будем честны, статистика упрямо показывает отток на мобильные устройства. А универсальность и скорость создания UI с помощью html, css и js выпихивает натив в узкие ниши. Конечно, скорость мобильных soc растёт, но, во-первых, всё равно упирается в батарейку (Snapdragon 8 прозрачно намекает), во-вторых, прирост производительности лучше отдать на логику UI, потому что быстрее разрабатывать и дешевле поддерживать. Вжух, MVP выкатываем...
И если принять как факт, что зайти на сайт совсем не тоже самое, что открыть магазин и установить приложение (а тут ещё тараканы с permissions), станет ясна заинтересованность бизнеса в PWA. В свете изложенного, наличие двух эндпойнтов, отличающихся даже только сортировкой, уже перестают казаться "бредовыми требованиями 'глупого' фронтендера". Ну, в самом деле, на бэке и вся логика под рукой, и лишний эндпойнт это пара строк кода плюс отдельная функция, что способствует лучшей структурируемости проекта.
olehorg
02.01.2022 22:47+2Многие фронтендеры относятся к беку, как к некой обертке для работы с базой данной. Когда такие становится лидом команды и начинают диктовать свои требования беку, начинается ад
если лидом становится бэк и начинает диктовать свои требования к фронту - получается еще хуже, особенно в плане юзабилити.
Собственно, для этого и существуют
архитектор - для того чтобы сформулировать первичные требованию к построению системы (включая взаимодействие и стек технологий)
-
всякие эти ваши скрамы - чтобы лид никому ничего не диктовал
Остальное - от лукавого.
а "Фронты могут проектировать API" - от особо лукавого лукавого.
jMas
03.01.2022 00:17+3Фронты могут проектировать, но только свою точку зрения на API - здесь нет ничего плохого. Потому что в реальности есть возможность отдавать дублирующиеся данные по нескольким эндпоинтам и удовлетворить потребности фронта.
Но часто для экономии ресурсов (времени и денег) код, берущий и трансформирующий данные из базы, пишется сразу в функции, которая их должна вернуть фронту (прям буквально все без разбиения: запрос в базу, перебор данных и трансформация, склеивание с данными из другого запроса, формирование JSON-ответа). И это тоже не плохой вариант, если требования снаружи минимальны, API не должен эволюционировать, и затраты на архитектуру не окупятся в перспективе. Как пример: какой ни будь промо-сайт с убер-фичей (показать рейтинги в режиме реального времени) для единичного заказчика под ключ (утрировано).
Проблемы начинаются когда появляется следующий эндпоинт с похожими данными и похожими трансформациями. Тогда разработчик делает: либо дублирование, либо начинает препираться с требованиями, либо заводит вопрос о рефакторинге. Тот вариант, который выберет разработчик - напрямую зависит от опыта и желания развиваться.
И из личного опыта: все негативные эмоции разработчики испытывают, когда одна из сторон не прислушивается и делает все "как правильно" с ее точки зрения (а точнее "как умеет"). Иногда доходило до смешного, когда не удавалось договориться о типах данных на уровне прямитивов.
411
03.01.2022 01:57+3Я бы в первую очередь рассмотрел проектирование API в широком смысле, без привязке к какому-либо протоколу передачи данных, будь то http по tcp/ip или обычный вызов функции.
Если мы берём API с одной функцией, вы просто хотите взять набор данных X и получить в ответ набор данных Y или сведения об ошибке, а так же, возможно, добавить какой-то сайд эффект, например, модификацию данных.
В этом смысле условный User GetUser(int id) и GET /users/{id} решают одну и ту же задачу.
Далее у вас есть вполне очевидное требование, что consumer и provider это не части одной программы и даже не находятся на одной машине.
Поэтому вы выбираете последовательно протоколы на 4-7 уровнях OSI. Обычно всё сводится к TCP/IP и HTTP. И в этот самый момент, если у вас есть человек, отвечающий за архитектуру, стоит выбрать какой-то стандарт, который вы будете использовать. Вы можете остановиться на REST, добавить к нему JSON API, или же можете взять GraphQL. Возможно вам нужно своё решение. В редких случаях, стандарт трудно принять или практически невозможно, но частично стандартизировать что-либо можно, например способ именования параметров или ещё что-либо.
Далее, если выбранный стандарт имеет достаточно хорошие соглашения и у фронта есть понимание, что в апи не будет никаких подводных камней, то возможно, что фронт может сам предоставить спецификацию апи. К примеру, это хорошо работает для всяких простых CRUD эндпойнтов. Но в любом случае со стороны бэкэнда должна быть проверка этой спецификации. Так же хорошие соглашения позволят обнаруживать фронтэнду уже существующие эндпойнты, которые могут помочь им решить их задачу.
Если же бэкэнд достаточно сложный, то фронтэнд спректировать апи не может, и всё, что может сделать фронтэнд, это дать бэкэнд разработчикам input и ожидаемый output и попросить апи, которое им предоставят. Вот тут вероятно то, что концептуально выглядит как одна функция на фронтэнде, может превратиться в более чем один вызов функции (а в вашем случае в несколько HTTP запросов), либо, в целях оптимизации, в новый и сложный эндпойнт, который делает то, что вам нужно за один вызов. И вот тут, если вы используете достаточно хороший стандарт, спецификация может оказаться лучшим языком общения. А может и не быть им.
В общем случае, фронтэнд разработчик может предложить спецификацию АПИ как способ выразить свои требования по инпуту и аутпуту при хорошей стандартизации этого апи, но финальное слово за бэкэндом, ибо только они знают все ограничения бэкэнда и лучший путь реализовать требования фронтэнда.
Нужно ли для такой коллаборации специальное решение? Не уверен. Но и критиковать ваш проект я не готов.
tendium
03.01.2022 03:35Если у вас публичное апи, и вы строго следите за версиями оного, то может spec first и хорош. Ещё spec first может быть удобен на первоначальном этапе проектирования. Однако если апи внутреннее и в строгом версионировании не нуждается (тут мне, конечно, могут возразить, мол, любое апи должно версионироваться, да только жизнь неидеальная штука), то кто-то потом должен всё это содержать в актуальном состоянии. И чем больше разработчиков (а ещё лучше команд) работает над проектом, тем больше риск расхождения спеки с реальностью. Можно, конечно, пойти обратным путём — генерить код на основе спеки, но не всем такой подход по душе (и, наверное, не на все случаи есть годные инструменты).
morsic
03.01.2022 04:38-1Кстати, напоминаю про еще один вариант - фронты пишут для себя прослойку на ноде, которая будет для них собирать с беков апи под себя. Офк это оверкилл на простых проектах, и требуется доверие к профессионализму других людей (чтобы не возникал срач про "ряя фронтендеры глупые, код писать не умеют").
tendium
03.01.2022 13:12Это называется, backend for frontend. Его, кстати, не обязательно могут писать разработчики фронтенда. И не обязательно на node :) Но он может лучше отвечать потребностям фронтенда и скрывать внутреннюю кухню.
saboteur_kiev
03.01.2022 05:30+2Да просто тимлид фронтов и тимлид бэков должны быть сопоставимы по квалификации, а не сеньор с одной стороны и малоопытный мид.
Либо более опытный должен принимать на себя обязанности архитектора, который будет сам ставить задачи и сам нести ответственность за продукт.
fpinger
03.01.2022 06:36-5В данной ситуации данные приоритет. Они на бэкенде. И ни одно API на спасёт их от противоричивости и следоватеольно, бесполезности. В частности для бизнеса. Фронтэндер рисует единорогов для бинеса. И ни один API не сделает их полезными. Ценность на бэкенде. И именно под картину ценности и не противоречивости данных нужно подстраиваться. Фронтэндер не решает таких задач.
И ещё одна психологтческая проблема. Фронтэндеров нужно сравнить с бугалтерией. Они обслуживают других, но гонор всегда у них. И здесь нет когого-то принежения. У всех своя роль, которая не лучше и не хуже других.
nin-jin
04.01.2022 14:36+1В данной ситуации данные приоритет. Они на сервере. И ни один бэк на спасёт их от потери и следоватеольно, бесполезности. В частности для бизнеса. Бэкендер рисует единорогов для фронта. И ни один бэк не сделает их полезными. Ценность на сервере. И именно под картину ценности и сохранности данных нужно подстраиваться. Бэкендер не решает таких задач. Их решает админ.
И ещё одна психологтческая проблема. Бэкендеров нужно сравнить с бугалтерией. Они обслуживают других, но гонор всегда у них. И здесь нет когого-то принежения. У всех своя роль, которая не лучше и не хуже других.
Каждый на конвеере считает свою работу самой важной, забывая, что без любого звена конвеер встанет.
rim89
03.01.2022 10:55Если вы один, и проект у вас под одного клиента - то нету смысла бекенду писать рандомный API, который потом не пойми как будет использоваться.
А если у вас система под множество клиентов, то явно главнй тут бэкенд.
Andreyneandrey
03.01.2022 11:06-5Я как фулл-стак разраб подтверждаю что фронтендеры это просто макаки. Их максимум кодерами назвать можно.
nickerlan
03.01.2022 11:36+1Бек обычно дальше от бизнес-требований, чем фронт, хуже понимание продукта. Ничем хорошим не заканчивалось, когда беку отдавался API на проектирование, куча времени утекало на коммуникации. Я пока пришел к реверс-схеме. Фронт пишет часть бека - ключевые dto, сразу задавая демо-данные. Фактически - мок сервер. В нашем случае - используется graphql с хорошо именованными резолверами. Где надо - делает комменты. Дальше кодогеренацией из gql-схемы рождается фронт-sdk, чтобы были единые контракты фронта и бека. Бек превращает мок-сервер в реальный, фронт в это время пилит фронт. По дороге вносятся небольшие изменения, но это сразу отражается в контрактах при кодогенерации и если что-то добавилось это сразу палится typescript-ом на фронте.
jakobz
03.01.2022 11:39GraphQL решает большую часть этих всех проблем. Мы уже 4 года только на нем, и я с ужасом вспоминаю всю ту дичь, которая была с REST.
breslavsky Автор
03.01.2022 11:50Как решаете проблемы с кэшированием в GraphQL? REST легко закэшировать на уровне nginx искользуя в качестве ключа URL. GraphQL все запросы шлются через POST при этом в одном запросе могут комбинироваться как фетчи так и мутации вместе.
jakobz
03.01.2022 13:23На уровне http мы ничего не кешируем. Мне не очень вообще понятно что можно в API кешировать на уровне http. Можно пример какой-то не синтетический? Вот в хабре, например - какие API можно и нужно закешировать?
А на уровне самого graphql - как что кешировать предельно понятно. Нод, которые graphql реализуют - можно напихать под балансер сколько хочешь, поэтому все это нормально скейлится.
breslavsky Автор
03.01.2022 13:43Вот отличная статья https://www.nginx.com/blog/nginx-caching-guide/
На хабре я бы закэшировал https://habr.com/kek/v2/inset/vacancies, а когда нужно сбросил бы кэш на nginx для этого урла.
Кэш на nginx очень дешевый, по сути это статика в памяти. nginx легко выдержит тысячи и десятки тысяч таких запросов без какого-либо масштабирования.
Если кэшировать на сервере приложений, это всегда значит обратку воркером типа uwsgi, что реально дорого и медленно вместо выдачи статики за миллисекунды.
mayorovp
03.01.2022 14:01-1И почему же это всегда дорого и медленно?
breslavsky Автор
03.01.2022 17:38Потому-что воркер очевидно требует больше ресурсов для запуска и работы, даже если в вашем коде Вы просто забираете данные из memcache например. И Ваш ответ не будет занимать 10 миллисекунд как при nginx кеше, а все 50-100 минимум.
mayorovp
03.01.2022 17:53-1Какой именно воркер и зачем он запускается на каждый запрос?
И да, за счёт какой такой магии файловый кеш может быть быстрее кеша в памяти?
breslavsky Автор
03.01.2022 18:32Вы меня минусуете просто так? :-)
Вот реальный пример, правда, я хочу предугадать Ваш следущий комментарий: вы неверно все настроили вот у вас и такая ситуация. Настроено верно, долго эксперементировали со всем чем можно.
Один из наших проектов https://www.esanum.de/
Смотрим ендпойнт
/api/apps/current/feeds/today/posts?page=1&page_size=14...
C кэшированием
nginx
ответ 77msx-cache-status: HIT
Отключеаем кэш https://www.esanum.de/?no-cache=1
C
memcache
там же 522 msx-cache-status: BYPASS
Как видим разница в 5-8 раз. И тут в целом все очевидно. Воркеры требуют дополнительных ресурсов. Nginx выдаст это как обычный статический файл.
Долго делали эксперименты c Python касаемо производительности, сверяли с GoLang и т.д. Python - тормозит :-) Жду Ваших минусов.
mayorovp
03.01.2022 18:45Ну хорошо, Питон — тормозит (хотя надо бы проверить что там вообще на сервере по-написано). Это что, единственный язык программирования?
breslavsky Автор
04.01.2022 00:28-1Это самый популярный язык программирования в мире. Плох он или хорошо - это предмет отдельной дискуссии.
breslavsky Автор
04.01.2022 09:04Видите, вы уже согласны. Уберете минусы :-)?
mayorovp
04.01.2022 11:24Вот только исходное обсуждение было не про Питон, а про бэк вообще. Это вы откуда-то решили, что если бэк, значит Питон, а если Питон — то только uwsgi.
breslavsky Автор
04.01.2022 16:04-1Вопрос был к кэшировании
graphql
и как вывод, что его кэшировать намного сложнее. Его кэш сложно засунуть в статический кэшnginx
.
siroBS
03.01.2022 20:26Смешались в кучу кони, люди...
У меня ваш сайт загрузился без кеша (на стороне браузера) в обоих случаях за одинаковое время.
Задача бэка выдавать различный ответ в зависимости от входящих параметров. А ежели вы кэшируете каждый вариант в статику, подразумевая огроменную нагрузку на ваш ресурс с одинаковыми запросами с одинаковыми входящими аргументами, может, стоит пересмотреть сам подход к структуре бэкенда [, фронтенда]. Не знаю как у вас там всё устроено, могу допустить даже, что Python каждый раз вычитывает шаблон с диска, наполняет и отдаёт. Тогда тупо загоните шаблоны при загрузке в удобную структуру данных Python и отдавайте прямо из оперативки, лучшего кэша и не придумать.
Кэш бывает разный для разных целей в разных местах. В портянке, на которую вы ссылаетесь, есть explanation use cases (между строк). На мой взгляд, у вас это выглядит как прикладывание подорожника к оторванной конечности одновременно с попыткой зашить рану от укуса комара.
Мне трудно поверить, что ресурс, который вы указали, трещит по швам от желающих его посетить настолько, что Python становится узким местом. Может, вы не используете asyncio с какой-либо обёрткой (aiohttp), это даст примерно такой же эффект, как замена HDD на SSD на 5-7 летних ноутбуках.
И вообще, на мой беглый взгляд, у вас там БЕДА. У вас ресурсов по сети загружается на 3 метра, картинок из них на 900Kb, распаковывается всё это хозяйство в 12-14 метров. Нет, вы серьёзно?!!! И если там, в недрах сайта есть что-то, что требует 12Mb ресурсов, но я не нашёл, то зачем сразу то всё загружать?!
-
Если честно, вот прям обидно стало за Python. :(
Ну да, он не такой быстрый как Go. Но тут... Вы просто не умеете их готовить...
Возможно, я тычу пальцем в небо и чего-то недопонимаю, но я старалсо... Чтобы вам минусов больше не ставили!
breslavsky Автор
04.01.2022 00:27-1Вы не заметили разницы из-за моего недочета - сорри (get параметр не используется больше), у нас кэш нужно отключить через
localStorage
, вот видео в подтверждение.По поводу 12 мегабайт ресурсов - то перед вами SPA приложение, которое лениво загружается к вам в браузер и это не значит, что для его работы требуются весь объем - оно кешируется на случай вашего серфинга по нему.
Задите пожалуйста на
youtube.com
и Вы увидите 12.6 мегабайт загруженных ресурсов - разве это может быть аргументом в неправильной архитектуре?На платформе проводяться онлайн конференции для докторов с нагрузкой порядка 5 тыс. онлайн пользователей, и если каждый запрос перенаправлять на сервер приложений для обработки Python это становится проблемой. В моем примере
nginx
выдает ответ в 3-5 раз быстрее, чем Python из memcache - это факт.Python - прекрасный и самый популярный язык программирования в мире. На нем быстро писать из коробки, но изначальная дискуссия была вообще в другом - в кешировании
graphql
. Проблема, в том, что, если можно выдать данные изnginx
- их лучше выдать оттуда, перенаправление на сервер приложений не может быть быстрее - это тоже факт. В случае сgraphql
сделать кэш наnginx
становиться сложнее, т.к. все запросы по сути это POST с телом с миксом фетчинга и мутаций.siroBS
04.01.2022 13:44Мне уже просто интересно стало...
Пусть у вас SPA. Я отключил кэш в браузере, поставил slow3G. До того момента, как я увидел простой блог без картинок, "лениво" передалось по сети 2Mb, распаковалось в 10 метров. Ну там как бы нет ничего такого, как на youtube.
Возможно, я просто не понимаю, но зачем вам вообще uWSGI, разве это не дополнительная сущность? В чём преимущество перед reverse_proxy на нужные ендпойнты на Python сервер за nginx?
Неужели такого рода кэш на nginx оказывается быстрее, чем ответ Python сервера, который соберёт всё в памяти, нежели nginx вычитает с диска? Возможно, стоит измерять весь pipeline пользователя, а не отдельные показатели?
breslavsky Автор
04.01.2022 15:54-1Пусть у вас SPA. Я отключил кэш в браузере, поставил slow3G. До того момента, как я увидел простой блог без картинок, "лениво" передалось по сети 2Mb, распаковалось в 10 метров. Ну там как бы нет ничего такого, как на youtube.
У youtube есть Service Side Render Cache, это когда в в первом запросе странице выдается ее полный кэш, после загрузуки SPA ресурсов, начинает работать уже SPA - у нас он еще не реализован, по разным объетивным причинам. Изначально, претензия была в количестве ресурсов, как признаке плохого проектирования. Вы именно так и написали.
Что такое в вашем понимании Python сервер? Кто примет запрос от nginx ? Кто запустит обработку Python в итоге? Разве не сервер приложений? Зачем тогда вообще
nginx
, почему Python сервер не может выдавать и статику тоже?
mayorovp
04.01.2022 16:33Зачем тогда вообще nginx, почему Python сервер не может выдавать и статику тоже?
…и такие решения существуют (наверное, для других языков они существуют совершенно точно).
nginx в подобной связке оставляют чтобы, во-первых, закрыть "детские болячки" сервера приложений, а во-вторых, дать сисадмину привычный инструмент который тот умеет настраивать.
breslavsky Автор
04.01.2022 21:59-1На каждый мой комментарий - минус, хотя ни в одном из них я не позволял себе аргументов типа:
детские болячки и привычный инструмент сисадмина
Не ужели в инженерной среде такие аргументы имеют место?
nginx
- стал популярен из-за в первую очередь снижения стоимости владения инфраструктурой.Возьмите статью по оценке производительности
nginx
Static Content. NGINX performs 2.5 times faster than Apache according to a benchmark test performed by running up to 1,000 simultaneous connections. Another benchmark running with 512 simultaneous connections, showed that NGINX is about twice as fast and consumed less memory.
Это аргумент?
mayorovp
04.01.2022 22:28А что не так с аргументом? У библиотек не бывает детских болячек? Сисадминам на настройку разных серверов требуется одинаковое время (включая те сервера, которые настраиваются только кодом)?
Static Content. NGINX performs 2.5 times faster than Apache
Apache пора закопать уже, а не сравнивать с ним nginx.
breslavsky Автор
04.01.2022 22:42-1А что не так с аргументом? У библиотек не бывает детских болячек? Сисадминам на настройку разных серверов требуется одинаковое время (включая те сервера, которые настраиваются только кодом)?
Эти аргументы - субъективные оценки, объективные аргументы инженера - это цифры.
Apache пора закопать уже, а не сравнивать с ним nginx.
И снова субъективная оценка. Давайте закопаем сервер который работает сейчас на 33% серверов в Интернете https://w3techs.com/technologies/comparison/ws-apache,ws-nginx
Снова минус? Хоть за что? За цифры? Мне просто интересна позиция инженера с такой кармой.
mayorovp
04.01.2022 23:12-1Вы пытаетесь сравнить производительность nginx и сервера приложений, для этого выбираете статью, которая сравнивает его с apache, и правда не понимаете в чём тут разница? Вы идиот или как?
breslavsky Автор
04.01.2022 23:23Очень жаль, что в инженерной среде когда адекватные аргументы заканчиваются, люди уходят в личные оценки и оскорбления.
Статью я привел как аргумент в пользу
nginx
как сервера с минимальной стоимостью владения инфраструктурой и метрик его скорости обработки статического контента в который можно загнать кэш ответов API.На последок ответьте тогда на такой вопрос:
Что будет быстрее и дешевле (управлять и масштабировать) выдать статический кэш с
nginx
или отправить его на сервер приложений с выдачей изmemcache
на масштабе 100 000 запросов в секунду?
siroBS
05.01.2022 00:33Я надеюсь, вы понимаете, что если даже Apache работает на 33% серверов в интернете, то это не повод его использовать, а повод скорее закапывать?!
siroBS
04.01.2022 17:27Ну, подчёркиваю, это только моё мнение, но я полагаю, что юзеру надо показать первую страницу так мгновенно, как это только возможно технически. Чтоб семантика отрендилась первой, особенно, если это просто блог. Причём, если это относительно лёгкая страница, показать её, а не спиннер. И пока он там думает куда дальше кликнуть, можно догружать остальное. Я понимаю, о чём вы говорите, но первая страница у вас, если без картинок, ну сколько может весить этот кусок html'а со стилями, копейки. А когда юзеру понадобится кусок тяжелого функционала, показать спиннер, если нужно. Я не знаю подноготной, но, на первый взгляд, это напоминает новостной сайт со статьями, мне тяжело представить, что для такого движка требуется сразу тащить в браузер 10-12 метров ресурсов. Возможно, я придираюсь и начинаю чувствовать себя неудобно. Давайте оставим, пожалуйста...
Python сервер, в моём понимании, это программа, которая сама прекрасно умеет в HTTP (websocket если надо), sessions, cookies совершенно без участия посторонних сущностей. И таки, да, прекрасно сможет выдавать и статику. Но это будет медленнее, нежели на статику поставить nginx, или вот Caddy полюбился. Плюс, nginx спереди берёт на себя гемор с безопасностью, а caddy умеет в автосертификаты HTTPS из коробки и простой конфиг. Такая конструкция избавляет от множества забот, позволяя писать в Python только логику. Я как-то прошёл мимо WSGI. Python серверы на aiohttp (TCP socket server, Андрею Светлову респект несомненный) делаю, просто reverse_proxy на нужные эндпойнты API прокидываю, так можно и нагрузку распределить на микросервисы, поднять несколько интерпретаторов (и GIL, внезапно, по-боку становится). Спереди и nginx был, но Caddy, конечно, очень вкусный. Я тут полез смотреть про uWSGI и не понимаю зачем сейчас это... Как я понял, это соглашение для функций Python, универсальный интерфейс, получается, это лишняя сущность из прошлого, когда Python не умел в полноценный сервер...
breslavsky Автор
04.01.2022 22:03-1Ну так все таки, что будет быстрее и дешевле выдать статический кэш с
nginx
или отправить его наPython
с выдачей изmemcache
на масштабе 100 000 запросов в секунду?
nin-jin
04.01.2022 16:19Задите пожалуйста на
youtube.com
и Вы увидите 12.6 мегабайт загруженных ресурсов - разве это может быть аргументом в неправильной архитектуре?Ютуб передаёт 700кб, но вобще, да, для его мизерной функциональности, это крайне много. И, к слову, об обезьянках и ютубе:
arthuriantech
03.01.2022 18:54Потому-что воркер очевидно требует больше ресурсов для запуска и работы
Вы что-то путаете, uWSGI работает в prefork режиме, его воркеры стартуют при запуске сервера однажды и затем параллельно обрабатывают запросы.
breslavsky Автор
04.01.2022 00:32Да я согласен, но дополнительный IO требуется для передачи от
nginx
доuWSGI
? Для масштабирования требуется запуск новых воркеров? Жедательно воркеров на разных машинах. Значит их нужно запускать - это ведь дороже в конечном счете чем кэш наnginx
. Или нет?
Suvitruf
04.01.2022 00:12+2Потому-что воркер очевидно требует больше ресурсов для запуска и работы, даже если в вашем коде Вы просто забираете данные из memcache например. И Ваш ответ не будет занимать 10 миллисекунд как при nginx кеше, а все 50-100 минимум.
Почему воркер nginx'а может работать быстро, а воркер вашего приложения не может? ????breslavsky Автор
04.01.2022 00:34-1Потому-что это дополнительный
IO
междуnginx
и сервером приложений, потом между сервером приложений иmemcache
.Suvitruf
04.01.2022 01:51+1У вас nginx, приложение и memcache находятся в разных датацентрах? Откуда там задержка в сотни мс?
breslavsky Автор
04.01.2022 01:57Но ведь вопрос был не в этом. Пускай даже сеть супер-скоростная, пускай даже это все на 1 компьютере, пускай мы ускорим и выиграем 10-30 миллисекунд. Зачем забивать сервер-приложений выдачей статики по сути? Это обязательно выстрелит при масштабе, когда запросов к серверу будет 10 тысяч. Лучше, если 9000 из них обработает сам nginx, а остальные сервер-приложений. Разве нет?
mvv-rus
04.01.2022 03:36Это может быть и не статика. Например, представим страницу с информацией о популярном товааре в онлайн-магазине. На ней есть:
1. Персонифицированные данные для клиента, с персональными предложениями и прочей маркетологией. Она — для каждого клиента своя, но для одного клиента меняется редко. В общем-то, место ей в кэше.
2. Навигация — она вообще для всех страниц может быть одинаковой. Место ей — в кэше (а то и вообще это статика)
3. Это самая информация о товаре — оно у каждого товара своя, но для всех клиентов — одинаковая. Если товар популярный, то имеет смысл закэшировать, чтобы каждый раз в базу не лазить.
А теперь попробуем все это закэшировать на обратном прокси (nginx или ещё каком). Если бы сайт был сделан по древним канонам — на фреймах — то никаких проблем, каждый кусок из 1-2-3 кэшируется независимо. Но сейчас так не делают, и кэшировать надо всю страницу целиком. И получается, что для каждого пользователя в кэше надо держать свою копию, со всеми вытекающими.
А на стороне веб-сервера можно закэшировать 1,2 и 3 как отдельные фрагменты — а потом быстро собрать из них страницу для выдачи. Не знаю как где, а в ASP.NET Framework эта функциональность есть из коробки, там даже силы тратить на ее реализацию не надо было.
breslavsky Автор
04.01.2022 09:02-1Все примеры которые вы привели, легко можно закэшировать статикой на nginx. Всегда вопрос только в ключе для кэширования.
Персонифицированные данные для клиента, с персональными предложениями и прочей маркетологией. Она — для каждого клиента своя, но для одного клиента меняется редко. В общем-то, место ей в кэше.
Ваш ключ на
nginx
- это URL ендпойна + токен пользователя из куки или заголовка.Навигация — она вообще для всех страниц может быть одинаковой. Место ей — в кэше (а то и вообще это статика)
Видите, вы уже почти согласны. Конечно статика, зачем тут сервер-приложений?
Вопрос изначально был про кэширование API, мы не говорили не про Server Sider Rendring, мы говорили про SPA.
mvv-rus
04.01.2022 20:26Все примеры которые вы привели, легко можно закэшировать статикой на nginx. Всегда вопрос только в ключе для кэширования.
Вы не поняли: вопрос — в количестве этих ключей. Одно дело, когда userID (в любом виде) — отдельно, а itemID — отдельно: число ключей кэширования (и копий в кэше) равно сумме числа разных userID и разных itemID, а совсем другое — когда ключ включает в себя и userID, и itemID: потенциально для кэширования той же информации потребуется число ключей кэширования равное произведению числа разных userID и разных itemID (плюс, сами кэшируемые куски больше, т.к. кэшируется вся страница).Конечно статика, зачем тут сервер-приложений?
Например, чтобы разделы для навигации создавать в CMS и хранить в БД. Ну и обратный прокси вынужден, в общем случае, хранить копию этих данных для каждой кэшированной копии страницы.Вопрос изначально был про кэширование API, мы не говорили не про Server Sider Rendring, мы говорили про SPA.
Ну, у меня, когда это все писал, в голове был ASP.NET Framework MVC, как вещь для меня лучше знакомая. Но с API ситуация будет примерно та же, только вместо страниц будет JSON. Он, конечно, объемом поменьше, но его точно так же можно было бы кэшировать по частям на сервере приложения и собирать из этих частей ответ, при том, что на обратном прокси пришлось бы хранить в кше ответы для каждой из используемых комбинаций userID и itemID.
breslavsky Автор
04.01.2022 22:48Ну так все таки, что будет быстрее и дешевле выдать статический кэш с
nginx
или отправить запрос на сервер приложений с выдачей изmemcache
на масштабе 100 000 запросов в секунду?
mvv-rus
04.01.2022 23:47Опять вы не хотите рассматривать проблему в общем виде: а почему именно memcache на масштабе 100 000 запросов в секунду; а если реальная нагрузка меньше; а если использовать не memcached с его сетевыми задержками, а локальное кэширование (вы же на его рассмотрение ЕМНИП согласились); а если ещё и ограничения по памяти для кэша рассмотреть — из-за которых промахи будут?
Короче, конкретные цифры надо смотреть для конкретного проекта, а если в общем, то схема с локальным кэшированием фрагментов — она тоже имеет область применимости.
breslavsky Автор
05.01.2022 00:03Слишком много если, вместо простого помещения результата ответа API в статический кэш
nginx
с супер низкой стоимостью владения. На 100 запросах +-1 секунда не будет заметна, а вот 100 000 вот тогда будет важен каждый лишний запрос на сервер приложений.
mayorovp
05.01.2022 00:26-1Какая нахрен плюс минус одна секунда? Откуда вы эту секунду взяли, "инженер"? Последуйте уже своему совету, поищите цифры в интернете!
К примеру, на Web Framework Benchmarks от TechEmpower верхние строчки все менее одной миллисекунды, а медианный результат — где-то 2.5ms. И это как раз на сотнях тысяч запросов в секунду.
breslavsky Автор
05.01.2022 00:36Не думал, что примите буквально. +-1 секунда на все 100 запросов имелось ввиду.
2.5ms
сюда включенIO
междуnginx
сервером приложений и напримерmemcached
?
mayorovp
05.01.2022 00:41+1Там другой сценарий рассматривался, с запросом в БД, но без кешей и без nginx. Но представление о порядке величин должно дать.
breslavsky Автор
05.01.2022 00:44Так это просто оценка скорости запроса в БД и все? Это не скорость обработки HTTP запроса с конечной выдачей ответа? Это очень разные вещи, очень.
mayorovp
05.01.2022 10:03Это оценка скорости обработки HTTP запроса под нагрузкой без кеширования (кроме как на стороне СУБД).
breslavsky Автор
05.01.2022 00:57Но в целом какая разница, ведь и так понятно, что
nginx
в итоге поместит это в RAM для востребованных запросов и не будетIO
с диска. А так тут же статья https://habr.com/ru/post/428127/
siroBS
05.01.2022 01:04В смысле?! А как же это?
https://stackoverflow.com/questions/38813399/cache-a-static-file-in-memory-forever-on-nginx
Из статьи, что вы привели: "Что же из себя представляет этот кэш? На самом деле это обычный файл на сервере". Похоже, только ключи в памяти кэшируются?
slapshin
05.01.2022 17:12+2https://stackoverflow.com/questions/38813399/cache-a-static-file-in-memory-forever-on-nginx
Здесь говорится о том, что сама OS кэширует часто используемые файлы - в этом случае получается своеобразный inmemory cache. Более того, если уж хочется - nginx может работать с memcached/redis (но только кэш придется для него формировать самостоятельно, но это несложно) - таким образом, при любом раскладе эту будет шустрее работать, чем перекидывать запрос на сервер приложений. Мне как бэкэнд разработчику кажется, что если есть возможность возвращать ответ, не задействуя сервер приложений - то лучше так и делать. Если не устраивает nginx - используйте varnish или что-то подобное. Возможно, для go это не так актуально, но в случае с python выручает (особенно когда используется django)
siarheiblr
03.01.2022 12:46+3Какая-то жесть описана. То ли люди не понимают, что такое командная работа, то ли не понимают, что они в принципе делают (не "пишу бэкэнд на джаве" а "пилим соцсеть для котов", хотя бы в таком ключе)
Всегда совместно работали с теми, кто будет пользоваться апи, потому что иначе запросто получается нечто совершенно непригодное к использованию. И сидеть и переделывать в итоге, так лучше уж сразу все обсудить.
souls_arch
03.01.2022 16:18ЗнаЕМ, пишЕМ, умеЕМ, используЕМ... Автор взялся отвечать за абсолютно всех фронтендеров? Это - не серьезно. Это - не профессионально. Так взрослые люди не пишут.
Не надо подводить частные случаи под общие правила и, даже, наоборот, - тогда и проблем с взаимопониманием не будет.
breslavsky Автор
03.01.2022 17:44-1Вопрос то ведь был поставлен так и никаки иначе:
Как считаете будущее за Spec-First Development или полный Agile (шутка): митинги, JSON-чики в чатиках и т.д.?
Разве это не для того, что бы обеспечить взаимопонимания? Вы как считаете?
mvv-rus
03.01.2022 21:18Как считаете будущее за Spec-First Development или полный Agile (шутка): митинги, JSON-чики в чатиках и т.д.?
А в общем виде этот вопрос не решается. Истина часто специфична для конкретных обстоятельств (моноокись дигидрогена — это жидкость или твердое тело, а?). В частности — от числа разработчиков: взаимодействие всех участников по принципу p2p — оно, конечно, выглядит привлекательно, но крайне плохо масштабируется. А потому приходится писать спецификации. Ну а дальше встает вопрос, кто это должен делать — и опять ответ на него зависит от конкретных условий.
breslavsky Автор
03.01.2022 17:50Я единственно, правда не совсем понимаю, почему многие пишут и комментируют статью в отрыве от самого текста? Почему нельзя взять любой тезис и на него написать комментарий.
Я писал про Spec-First именно (для этого и был сделан Swagger / Open API) про то, как можно согласовать требования заранее к API без "чатиков" и "JSON-чиков", вопрос был только в этом.
mvv-rus
03.01.2022 21:12+1Я единственно, правда не совсем понимаю, почему многие пишут и комментируют статью в отрыве от самого текста?
Мое личное мнение — потому что сам текст такой. Вы сначала затрагиваете весьма общую проблему — архитектуру веб-приложения и зоны ответственности его разработчиков, но потом предлагаете очень частное ее решение — для ограниченного числа возможных архитектур, да ещё и с привязкой конкретным инструментам. Причем — предлагаете без привязки к конкретной архитектуре.
Вот комментаторы и комментируют не ваше очень частное решение, а ту самую общую проблему и ее решение в общем виде для разных других обстоятельств, от которых сама архитектура может зависеть весьма сильно и быть очень не похожей на вашу.breslavsky Автор
04.01.2022 00:38Что я предлагал? Я лично ничего не придумал. Есть Swagger - Spec-First - не я это придумал. Я лишь, описал как хорошо писать спецификации на API заранее или нет?
Причем тут ограниченность архитектур?
Напишите контракты, выполните их, проверьте, что все выполнено - разве не хорошо?
mvv-rus
04.01.2022 02:35Что я предлагал? Я лично ничего не придумал.
Ну, может, не вы лично, а ваша команда. Но вы — таки предлагали:Мы в команде давно используем Swagger, мы пишем его заранее на фронте, потом передаем на бэк, что бы они реализовали, что нам нужно.
…
И спустя пару месяцев мы разработали – API Projector — Визуальный Swagger редактор
API projector – это визуальный Swagger редактор с возможностями привязки API к пользовательскому интерфейсу системы (приложения).
То есть, предложили (неявно, описывая ваш процесс работы) создавать описание на стороне фронта (хорошо, с согласованием у бэка, но бэк играет в целом пассивную роль в процессе разработки API), указали формат описания API (если чо, его можно и просто на бумажке написать) и инструмент создания описания в этом формате. То есть вы достаточно детально описали процесс создания спецификации API.Есть Swagger — Spec-First — не я это придумал.
Вы придумали процесс создания API. Это хорошо, это правильно. Но в его описании все сложили в одну кучу. Spec-First — это концепция, она же паттерн, вещь весьма абстрактная. А Swagger — это весьма конкретный набор средств для работы с конкретным форматом описания API.
Ну, и этот процесс не всем и не всегда может подойти. Например, если для облегчения нагрузки на бэкенд (или на его разработчиков ;-) ) преобразование из модели представления (тот набор сущностей, которые пользователь видит и с которыми работает в приложении) в модель данных предметной области решено вынести на фронтенд. Тогда API будет основан не на модели представления а на модели предметной области, и источником информации для его создания станет бэкенд. И логично, чтобы спецификации API шли от бэка.Причем тут ограниченность архитектур?
Ограниченность тут — в том смысле, что возможны архитектуры приложения, в которых ваше решение неоптимально. Пример — выше.Напишите контракты, выполните их, проверьте, что все выполнено — разве не хорошо?
Это как раз очевидно. И если бы в вашей статье была бы только эта мысль, то возможно и статьи бы не было. ;-) Но у вас есть и другие мысли — и их тут обсуждают.
PS Прошу прощения, если я пишу как-то абстрактно. Увы — как умею.breslavsky Автор
04.01.2022 09:18Спасибо за комментарий, но мне несколько странно в качестве аргмумента видить запись API контракта на бумажке. Писать контракты на Swagger не моя идея - он для этого и был предназначен.
Многие думают, что Swagger (Open API) – это «UI шкурка», которую генерирует в конечном счете бек из кода, они не понимают, что это в первую очередь – JSON схема описания API.
Вот свежий курс по проектированию API
Теперь поговорим о подходе, основанном на спецификации. Многие считают, что автогенерация, описанная в предыдущем разделе, - не лучший подход. В книге «Undisturbed REST: A Guide to Designing the Perfect API» Майкл Стоу рекомендует командам реализовать спецификацию OpenAPI вручную, а затем рассматривать документ спецификации как контракт, который разработчики используют при фактическом кодировании. Этот подход часто называют «разработкой на основе спецификации».
Другими словами, разработчики обращаются к документу спецификации OpenAPI, чтобы узнать, какие имена параметров следует вызывать, какими должны быть ответы и т. Д. По словам Стоу, после того, как этот «контракт» или «план» был установлен, вы можете поместить аннотации в свой код (если хотите), чтобы сгенерировать документ спецификации более автоматизированным способом. Но не пишите код без предварительной спецификации.
Все выводы вы сдедали сами. Подход не претендовал, на все случаи жизни.
Напишите контракты, выполните их, проверьте, что все выполнено — разве не хорошо?
Именно только она и была, как в вашем случае на бумажке повторить данный процесс?
mvv-rus
04.01.2022 20:27Подход не претендовал, на все случаи жизни.
В вашей статье так не написано. Или я пропустил нужное место?breslavsky Автор
04.01.2022 22:46А этого места нет. Выводы вы сдедали сами, что это подход на все случаи жизни. Я честно говоря, думал, что вы больше прокомментируете :-(
Хотя бы это:
Многие думают, что Swagger (Open API) – это «UI шкурка», которую генерирует в конечном счете бек из кода, они не понимают, что это в первую очередь – JSON схема описания API.
mvv-rus
04.01.2022 23:50-1А этого места нет.
Так сделайте его, напишите про это в явном виде. Иначе многие будут из-за этого считать, что вы претендуете на универсальность (кстати, по комментриям это видно, что немало комментаторов именно так все и поняли).
Или напишите что вы не согласны с тем, что API всегда должен определять бэкенд: отрицанием утвержднения с квантором всеобщности как раз будет утверждение с квантором существования верного обратного утверждения
iloer
04.01.2022 00:42Отвечая на вопрос - я действительно верю в spec-first и активно продвигаю его в своих командах
Переходя к тексту статьи.
Мне лично кажется, что у вас в голове каша из множества различных областей процессов разработки и управления. Попробую систематизировать и предложить примеров.
Давайте попробуем обозначить основные компоненты вашего повествования, ими являются бэкэнд и фронтэнд. Какие у них роли? Бэкэнд можно сравнить с поставщиком некой продукции/данных (автопроизводитель, молочная ферма, онлайн ресурс) в свою очередь фронтэнд - это потребитель данной продукции (автовладелец, покупатель в магазине, клиент сервиса), чем же в данной аналогии является спецификация? Все верно спецификация это - "инструкция по эксплуатации" автомобиля. Исходя из предложенных аналогий выходит, что существует конкретный предложенный продукт и множество разнообразных его потребителей. Становится видна на мой взгляд вся абсурдность вашего требования, которое подразумевает обязанность производителя в согласовании инструкции с каждым возможным потребителем. Как вы представляете себе процесс согласования API какого-нибудь Aviasales или Reddit с сайтом-визиткой отображающим цены на последний перелет или количество комментариев reddit, странно звучит, не правда ли?
Переходя к процессу актуализации спецификации тут все тоже становится прозрачнее, стоит лишь определить ее владельца. Кто является владельцем API, ну конечно же сервис который его предоставляет и реализует - бэкэнд. А значит достаточно иметь один файл спецификации (json, yml) в репозитории бэкэнда. Где все внутренние потребители смогут его прочитать, предложить свои комментарии/исправления по средствам merge request.
Ситуация когда конкретному потребителю нужно оптимизировать/кастомизировать некие запросы для удобства восприятия ответов, не является уникальной и для ее разрешения с сохранением ответственностей описан паттерн BFF ( back for front) задачей которого и является удовлетворение потребности конкретного потребителя. Приходя к аналогиям его можно сравнить с тюнинг-анелье, которое на вход получает "голый" продукт от производителя, а на выход выдает то, что попросил отнего конкретный клиент. В этом случае спецификацию bff сервиса может составлять и фронтэнд, ровно в том виде который ему нужен. Причем не обязательно воспринимать bff как отдельный сервис (хотя очень желательно) это вполне может быть и отдельное адресное пространство оригинального бэка.
P.S. сразу попрошу прощения. Неожиданно длинный получился комментарий.
breslavsky Автор
04.01.2022 01:03-1Спасибо за развернутый комментарий.
Но мне несколько странно, что Вы написали:
Мне лично кажется, что у вас в голове каша из множества различных областей процессов разработки и управления. Попробую систематизировать и предложить примеров.
Ведь в моей статье был тезис про разделение слоя бизнес-логи и API.
@breslavsky Мне кажется проблема в том, что некоторые бекенд разработчики, неверно понимают разработку бизнес-логики и разработку интерфейса доступа к ней и к данным. Интерфейс на бекенд может быть HTTP, сокеты ли даже командная строка. Это всего лишь интерфейс. Эти разработчики при проектировании ендпойнта
/login
часто зашивают в контроллер бизнес-логику, работу с базой, генерацию сессии и т.д. И именно поэтому они связывают проектирование API с разработкой кода функции и именно поэтому когда им нужно добавить, например, GraphQL им нужно дублировать код.Пожалуйста, производитель создал слой бизнес-логики. API - слой общения с ней.
Я как отдельный класс потребителя web-приложение требую выдать последние комментарии с Reddit оставленные пользователями в нерабочие дни в USA, потому-что продуктологи хотят сделать тест на новую фичу. Другие внешние системы которые сейчас тоже запрашивают API с Reddit врядли, когда-либо потребуют такой ендпойнт.
Где тут проблема?
iloer
04.01.2022 08:27Проблема как раз в том, что будет ли реддит расширять свой публичный api под ваш "уникальный" запрос, или предложит воспользоваться уже существующим.
breslavsky Автор
04.01.2022 08:49Опять вопрос на вопрос. Мы - есть комманда Reddit - его бекенд и фронтенд. Теперь такой кейс реально существует?
И ответ, то бы на кашу в голове :-)
iloer
04.01.2022 11:29+1Все ваши утверждения строятся на убеждении, что у бэка в сеть ровно один фронт. Это в корне не верно и в реальных проектах даже у одного продукта есть множество различных фронтов (веб, мобильный веб, мобильное приложение, разный веб для разных регионов) во что превратится ваш API если каждый из представленных потребителей начнет требовать свои уникальные методы выполняющие по факту одни и те же действия? Этот API в итоге не возможно будет ни поддерживать, ни развивать. Задача ядра системы предоставить полный набор методов для работы с бизнес-сущностями системы и реализовать их поведение согласно бизнес-логики системы безотносительно того как и где эти сущности будут представлены. Следовательно бэк не может и должен ничего знать о конкретном фронте, и тем более подстраиваться под него.
В свою очередь задача фронта, используя представленные методы показать интерфейс системы обеспечивающий удобный способ взаимодействия для конкретной, часто узкой части аудитории, при том что пользовательский интерфейс очень редко использует весь спектр возможностей системы. Фронт не может и не должен ничего знать о деталях реализации системы, только представленный АПИ.
Под кашей я имел ввиду то, что вы перемешиваете (размазываете) ответственности компонентов системы повышая тем самым связанность. Ваш фронт начинает влиять (а значит заботиться) о бэке, а бэку при развитии приходится учитывать особенности каждого фронта. Цена развития в такой системе лавинообразно растет с появлением нового фронта, и это уже не говоря о поиске и исправлении дефектов.
breslavsky Автор
04.01.2022 15:59Если бизнес-логика отдельно почему нельзя предоставить к ней доступ сразу через API: REST, SOAP, командную строку разным клиентам исходя из их потребностей. Где тут все таки каша? Ваш бизней слой идеален, модель данных идеальна. Вы просто педоставляете к ней доступ исходя из потребностей клиентов.
iloer
04.01.2022 20:12Вот например я как поставщик продукта и выбрал единственный приемлемый для себя ( тот за работу и актуальность которого я готов отвечать головой) способ предоставления доступа, пускай это будет REST. И пускай все возможные потребители сами решают как и в каком виде они будут его потреблять. Кто-то будет слать запросы на прямую, кто-то напишет BFF-сервисы для преобразования запросов/ответов. Кто-то вообще приделает CLI и буде радоваться консоли. Это уже не моя забота как поставщика. Моя задача гарантировать работоспособность того единственного канала, который я предоставил.
nin-jin
04.01.2022 20:57На другой стороне сидит точно такой же "царёк", который сделал апи для интеграции, а остальное - не его, как потребителя, забота. В конечном счёте подстраивается тот, кому больше нужно.
iloer
04.01.2022 21:45На мой взгляд, в данном контексте термин "царек" неуместен, так как речь идет не о власти, а о ответственности. Вы же не ожидаете, что уборщица в вашем доме начнет готовить вам еду (хотя вероятно могла бы), или сотрудник ДПС на дороге не только выпишет протокол, но и примет у вас оплату втрафа на месте (хотя вероятно мог бы :) ).
breslavsky Автор
04.01.2022 22:20Вот например я как поставщик продукта и выбрал единственный приемлемый для себя ( тот за работу и актуальность которого я готов отвечать головой)
Очень странное для себя. Разве не задача любого исполнителя выполнить требования заказчика на компромисе стоимости реализации, надежности, расширяемости и т.д.
Как вы считаете по стоимости масштабирования: дергать 2 запроса с бэка вместо одного для отображения одного UI блока на фронте - это дешевле или дороже, чем просто реализовать это в API для фронта? Или дешевле сделать промежуточный сервис который в итоге все равно дернет API 2 раза, но на фронт вернет это одним ответом? В итоге в системе будет один промежуточный узел со всеми вытекающими проблемами типа кэширования, сложных выборок из базы данных и т.д.
iloer
04.01.2022 22:58+2просто реализовать это в API для фронта
Вот вы снова упускаете важнейшую деталь. Для какого конкретно фронта нужно реализовать АПИ? каждому фронту нужно свое, уникальное АПИ.
Отвечая на вопрос: Всегда дешевле реализовать все в одном месте, собрать прототип "на коленке" и выдать заказчику в качестве продакшен решения. Все будут просто без ума от вашей скорости и професионализма, но когда этот же заказчик придет к вам и скажет, что к вашему отличному решению теперь нужно написать мобильное приложение, и еще рядом такой же интерфейс, но допустим для пенсионеров. Вы во первых пойдете писать новую спецификацию под уже реализованные фичи, во вторых начнете привлекать вторую команду (помимо вашей) для реализации нового АПИ, и если вдруг, недайбог каким-либо образом реализация нового АПИ повлияет на существующее (а мы понимаем, что вносим изменения в код уже работающего решения и кто его знает, кто там в чем также сэкономил и решил не разделять код на отдельные модули) вам придется еще и перетестировать ту часть решения, которая вроди бы и не менялась. Все это вместе да, конечно будет значительно дороже, чем написать сервис-адаптер влияние которого будет ограничего конкретным потребителем.
breslavsky Автор
04.01.2022 23:07Но я же писал выполнить требования заказчика на компромисе стоимости реализации, надежности, расширяемости и т.д.
В моей системе я бы спроектировал идеально бизнес-логику и модель данных. Добавить новый ендпойинт, что бы принять или отправить что-то из нее не составило бы труда или нет?
В моей статье было это:
Мне кажется проблема в том, что некоторые бекенд разработчики, неверно понимают разработку бизнес-логики и разработку интерфейса доступа к ней и к данным. Интерфейс на бекенд может быть HTTP, сокеты ли даже командная строка. Это всего лишь интерфейс. Эти разработчики при проектировании ендпойнта
/login
часто зашивают в контроллер бизнес-логику, работу с базой, генерацию сессии и т.д. И именно поэтому они связывают проектирование API с разработкой кода функции и именно поэтому когда им нужно добавить, например, GraphQL им нужно дублировать код.
iloer
04.01.2022 23:15Извините, но мы ходим по кругу, вынужден завершить эту ветку обсуждения.
Основные арументы с обоих сторон уже высказаны.
breslavsky Автор
04.01.2022 23:30Спасибо за дискуссию, за кашу обидно :-) Это же личностные оценки, что в инжеренной среде мне кажеться не уместно.
mvv-rus
04.01.2022 20:28Все ваши утверждения строятся на убеждении, что у бэка в сеть ровно один фронт. Это в корне не верно и в реальных проектах даже у одного продукта есть множество различных фронтов
Если у бэка есть несколько существенно разных по функциональности фронтов (несколько типов АРМ работников или клиентов), то для каждого фронта можно создаеть свою модель представления (набор отображаемых в ней сущностей и действий с ними) и использовать API, основанный на этой модели. Да, бэку в этом случае придется потрудиться, преобразуя данные из модели предметной области в нужную модель представления и обратно (и программистом бэка — тоже, программируя это преобразование). Но и преимущество в таком подходе есть (и даже для единственного фронта): модель представления для фронта изолируется от модели предметной области, и эти модели (и основаннные на них спецификации API, классы DTO, струтуру БД) можно менять независимо.
В таком подходе предложения автора статьи — вполне годные для использования (особенно, если учесть, что фронт может по жизни являться источником сведений о хотелках пользователей).
А использовать ли такой подход, или какой-либо другой (например, API, прямо отображаемый на модель предметной области, чтобы разгрузить бэк — серверы или программистов) — это зависит от конкретного проекта.iloer
04.01.2022 20:40Ну так собственно о таком варианте и шла реч в моём первом сообщении. То что вы описали полностью попадает под описанного мною BFF-пасположенном не в виде отдельного сервиса (приложения) а в виде отдельного адресного пространства того же сервиса.
для каждого фронта можно создаеть свою модель представления (набор отображаемых в ней сущностей и действий с ними) и использовать API, основанный на этой модели.
Разве не выглядит это как дополнительная обязанность, которая вполне может быть выделена в отдельный микросервис например? Заниматься ей в этом случае может как команда основного фронта, так и выделенная команда, что в савокупности повышает гибкость процесса разработки в целом. И я уже не говорю о том, что такой сервис может быть написан на стеке, отличном от стека основного бэка.
Ilusha
04.01.2022 03:53А давайте я приведу другую аналогию.
Производство процессоров, упрощено: завод(бэк) формирует требования к спецификации по которой он произведёт продукт, заказчик её готовит, отдаёт и получает нужный ему продукт.
Или ещё другой пример: тендеры. Потребитель четко указывает свои требования.
Да даже в автосалоне заказываешь автомобиль в нужной комплектации, а потом ждёшь, когда ее произведут.
И отсюда можно сделать вывод: аналогию всегда можно использовать только для иллюстрации, чтобы сделать идею понятнее (почти всегда, если рассуждать об аналогии с позиции философии).
-
Каждый подход имеет границы применимости.
breslavsky Автор
04.01.2022 08:52Спасибо, за поддержку. Такое ощущение, что разрабочики сразу любят бежать в код и потом договариваться в чатиках и JSON-чиках, вместо того, что бы спроектировать, как это будет выглядить до разработчки, что бы начать работу паралелльно.
sherbinko
03.01.2022 23:08На самом деле, не так важно кто пишет спецификацию: фронт или бакэнд.
Но, очевидно, она не может рисоваться ни в каком UI - инструменте. Это гигантский шаг назад во времена, так-называемых, кейс-средств и визуальных языков программирование а-ля дракон.
Вся индустрии софтостроенния идёт в сторону "текстофикации": asciidoc, PlantUML, развёртывание софта по декларативням описаниям и пр ... . С текстом работать на порядки удобнее, его можно легко мерджить и отслеживать.
Далее: кодогенерация - зло. Всё-таки, API делается в (условно) Java-классах, где прописывается аннотациями аттрибуты и методы.
Прописывать API в XML или yaml файлах - это пустая трата времени, это криво и неэлегантно. Опять же, возврат во времена доклетов и кейс-средств.
breslavsky Автор
04.01.2022 01:09-1Спасибо за комментарий. Разрешите привести в качестве аргумента https://swagger.io/tools/swaggerhub/
The Single Source of Truth for API Development
Join thousands of teams who depend on SwaggerHub to get their products to market, faster 100k+ API Practitioners, 40k+ Organizations, 200k+ API Projects
Складывается ощущение, что на текущий момент такой подход просто еще не пришел на Хабр.
mvv-rus
04.01.2022 03:10+1Но, очевидно, она не может рисоваться ни в каком UI — инструменте.
Не очевидно. Потому что ничто не мешает UI-инструменту сохранять результаты работы в текстовом формате. Например, редактор диалогов из состава средств разработки MS программ на Windows с древних времен делал именно так: читал текстовый нескомпилированный файл ресурса диалога (расширение rc), отображал его в GUI (где можно было на все элементы полюбоваться, мышкой их подвигать и т.д.), и потом сохранял результат в тот же самый текстовый файл — со всеми упомянутыми вами преимуществами в плане работы с ним.
pavelsc
04.01.2022 10:22-1Я так понимаю архитектор с вашей гордой шхуны ушел? Попробуйте сначала в confluence пару недель поописывать, то что вы собираетесь делать. Почему-то часто разрабы считают себя выше того, чтоб писать куда-то кроме IDE и не код.
То что сваггер что-то ускоряет это миф. Ведь нельзя что-то ускорить, если вместо 40 спринтов взять 42 и ускорять не нужно, зато сделать SDK с валидацией и у вас не останется бесполезного YMLика. Ди в конце концов у вас не 400 эндпойнтов, будет 20 или около того. Экономия на спичках.
breslavsky Автор
04.01.2022 16:02Вот зачем такие голословные оценки? Мы давно используем все возможные иструменты в своей работе.
Почему-то часто разрабы считают себя выше того, чтоб писать куда-то кроме IDE и не код.
Как раз таки Swagger и решает эту проблему. Напиши контракт до кода, напиши код и проверь контракт.
То что сваггер что-то ускоряет это миф. Ведь нельзя что-то ускорить, если вместо 40 спринтов взять 42 и ускорять не нужно, зато сделать SDK с валидацией и у вас не останется бесполезного YMLика. Ди в конце концов у вас не 400 эндпойнтов, будет 20 или около того. Экономия на спичках.
Очень не однозначно. У вас будет 20 ендпойнтов, но в 200 раз больше запросов к бэку. Как это скажеться на производительности?
tempick
04.01.2022 17:01Почему-то часто разрабы считают себя выше того, чтоб писать куда-то кроме IDE и не код.
Или просто лень) (как мне, например)
katletmedown
Вы предлагаете использовать визуальный редактор для проектирования. Напомню, что бэкендер для создания контракта использует код (со всеми сопутсвующими плюшками, которые предоставляют IDE и git), абстракции, и получает сваггер автоматически.
GooG2e
Подскажите, а что в эту сторону посмотреть - как из swagger генерируется заготовка кода видел, а наоборот не пытался. Подскажите что посмотреть, пожалуйста
katletmedown
Да вот хотя бы FastAPI так делает из коробки
danial72
Gui - просто сокращение механической работы. Что ворчать на него ?
OpenApi дает тот же самый результат, просто менее удобно
iliazeus
Для ASP.NET Core есть, например, Swashbuckle.
breslavsky Автор
Это генерация из кода, это не Spec-First.
werevolff
Слушайте, ваш подход spec-first имеет место быть. Но не везде. Я сталкивался с ситуациями, когда требования к API мегялись в процессе разработки и тестирования. Наш фронтендер потребовал сохранить старый контракт на API, и мы получили в итоге очень проблемные баги, которые решали две недели. А ещё, некоторые движки, типа Django, имеют определённые ограничения при разработке обёртки. Движок выбирается по многим причинам, и если фронтенд начнёт создавать для такого движка контракты на апи, то это приведёт к расходам и проблемам. Будем объективны: в абсолютном большинстве ситуаций фронтенд не может делать контракт на API по объективным причинам. Например, потому, что смена схемы вывода данных, инициированная бэком, может ускорить запрос к бд. Или потому, что у движка есть ограничения. Или потому, что фронтендер не является опытным архитектором АПИ. В большинстве случаев, фронтенд реально нуждается только в том, чтобы бэк вернул определённые данные, а форма этих данных важна лишь в минимуме ситуаций. Плюс, вынести часть расчётов на фронт - это нормально. Бэкендер ограничен производительностью сервера, а фронтендер в большинстве ситуаций может не беспокоиться о производительности пары лишних циклов. Поэтому, ваш подход слишком радикален. Да, есть ситуации, когда бэк обязан вернуть ответ по контракту фронта. Но это слишком редкие ситуации, когда реально фронт нельзя переписать. И меня смущает, что вы в своей статье не затронули вопросы ограничений бэка и фронта, которые могли бы вывести ваш подход на более логичные рельсы. Например, как вы собираетесь обходить ограничения движка? Как собираетесь реагировать на необходимость оптимизации запроса к бд посредством смены API схем? Если ваш подход работает в обстоятельствах, где эти детали не критичны, то так и пишите: этот подход работает на лоу-лоаде сервера, когда проблемами бэкенда можно пренебречь.
Я лично использовал вариант, когда опрашивал фронтэнд разработчиков, и они мне кидали образцы json, которые я мог воспроизвести в API. Увы, в том числе, фронтендеры не всегда давали проработанный вариант, и контракт приходилось менять по разным причинам. Были ситуации, когда я программировал и по схеме контрактной разработки АПИ, но контракт прорабатывался и для фронта, и для бэка, с учётом всех возможных ограничений и подводных камней.
breslavsky Автор
Попробуйте пример https://editor.swagger.io/
JSmitty
Ммм, я думал что созданием контракта должен рулить некто "архитектор". Понимающий, как система в целом будет функционировать. А не только какая-то из её частей. Если, конечно, одна из частей не является анемичной (REST поверх хранилища данных, или наоборот тонкий UI на клиенте).
baldr
Конешн, вам там в энтерпрайзе хорошо - три вида архитекторов, техлид с тимлидом, код-ревью, митинги-шмитинги и печеньки с пивом по пятницам.
А бывает и так что клиент нанимает тебя на проект и говорит - вон там в скайпе сидит еще какой-то парень, он (уже) два дня делает фронтенд, я ему все объяснил как хочу видеть, договоритесь там сами.
Dilbert strips
katletmedown
не вижу противоречия, разве что архитектор только мышкой умеет проектировать)
baldr
Вот опять не удержаться от комикса
thatsme
Похоже, что у вас очень депрессивное рабочее окружение, что за конторка? Меняйте пока не поздно. Развиваться в окружении такого кол-ва болванов, очень сложно ...
katletmedown
тут недопонимание возникло) это сарказм был
CrocodileRed
Насколько я в теме, архитекторов вещи типа формата json не волнуют от слова совсем и я их отлично понимаю:-)
nin-jin
Конкретные имена полей его может и не интересуют, но вещи типа протокола взаимодействия, чтобы эти разные сорта обезьян не изобретали 100500 не совместимых вариантов rest-api, нормального архитектора очень даже интересует.
CrocodileRed
В статейке речь не о протоколах, а именно о форматах.
nin-jin
В статье речь про swagger, а это именно что описание протокола, причём не универсального, а отдельная спецификация на каждый эндпоинт.
CrocodileRed
Я могу ошибаться, но мне кажется, что мы под протоколами разное подразумеваем :-) Вы таки из фронта?)))
Ilusha
Мне всегда казалось, что этап проектирования находится до этапа кодирования.
Визуальная среда, в данном случае, позволяет быть в одинаковом контексте: это уже не сырой ux, для которого нужно API. Фронты готовят draft-контракт, который уже совместно доводится до ума, финализируется. И показывают, почему они видят именно так.
Это же облегчение работы бэкам, позволяет фронтам планировать развитие, даёт возможность работать параллельно с помощью временных заглушек, круто же. Можно завести, конечно, роль архитектора/аналитика и т.п. Но если их нет, а есть только PO, фронт и бэк, то почему бы и да. Процесс имеет полное право на жизнь и я не вижу фундаментальных проблем.
-
А сваггер, который генерироваться автоматически - это уже реализованные в коде контракты (интерфейсы контрактов? я тут не знаю деталей), ведь так? Т.е. без обсуждений есть риск потратить время на контракт, который не подходит для бизнес-логики фронта?
katletmedown
Да это просто декларация классов и типов полей, нет там никаких особых трат времени.
Ilusha
А какой процесс предпочитаете Вы?
katletmedown
Ровно так и делаю, если у фронта есть пожелания, вношу изменения или обсуждаем и оставляем. Обычно угадать его желания заранее несложно.
Ilusha
Ну, то же самое, только с другой стороны.
Положа руку на сердце, мне, как фронту, такой подход нравится больше: если бэк сам вникает в то, что требуется от ux, сам строит модели, увязывает всё, то мне меньше работы. Ведь что нужно мне? Модель данных, по которой я могу работать, даже если бэк ещё не реализовал api.
breslavsky Автор
А коммуникация в чатах с JSON-чиками?
katletmedown
ссылка на сваггер
breslavsky Автор
Он сгенерирован на базе кода уже или написан в YAML заранее?
katletmedown
автоматически сгенерирован, конечно
breslavsky Автор
А перед кодом, что-то было? Фронты как-то учавствовали в обсуждении того какие данные придут с бэка? Какие параметры при этом нужно передавать?
Или бэк сделал как это пока сам видит?
katletmedown
обсужается функционал, в абсолютном большинстве случаев бэку достаочно знать, какая задача решается, чтобы предоставить пользователю апи необходимый и достаточный набор данных, у него же в голове есть вся схема хранения данных либо архитектура системы если это не просто crud
breslavsky Автор
Вот самый главный вопрос как это обсудается? В чатах с
JSON
? На митинге голосом?Что если вместе открыть редактор и писать сразу контракт, а потом начать работать паралельно? А потом еще и проверить, что он выполнен правильно? Лишняя не нужная работа? Интересно ваше мнение.
GET /users/{id}
User
katletmedown
параллельная работа, боюсь вызовет у вас желание написать еще один пост, если вы узнаете, что задачи фронту тоже ставит бэк)
не вижу смысла обсуждать контракт, бэк просто его напишет так, как нужно) близко к структуре, в которой данные хранятся и чтобы фронту было при этом удобно с этим работать. а что контракт выполнен - тут может быть только одна проверка, - фронт работает) потому что тесты апишки уже успешно прошли автоматически.
breslavsky Автор
Спасибо за комментарий, но аргументы немного странные, извините.
Получается, фронты вообще не нужны. За них все придумает бэк. Вопрос, точно ли он сделает все как нужно. А потом митинги, согласования, изменения и т.д.
Бэк выдает все 20 полей из сущности, а фронты выведут только 5 и эти 15 оставшиеся будут бегать по сети просто так и есть траффик пользователя и время на сериализацию.
katletmedown
Я же говорил выше, что бэк даст необходимое и достаточное количество данных) Либо, да, даст лишние, если посчитает что издержки на написание и поддержание лишнего кода не оправданы (если можно легко переиспользовать старый код, например). Если компетенции бэка на это не хватит - чтож, как вы и говорите, начнутся митинги(
А может вам всем вместе стоит просто один раз все обсудить)
Chamie
Чтобы он дал необходимое и достаточное, он должен понимать, как будет работать фронт. Но тогда это не чистый бэкенд-разработчик
breslavsky Автор
Очень много если. Почему нельзя отдать на бекенд по-сути ТЗ записанное в виде контрактра на Swagger, а не полагаться на его профессионализм и "понимание фронта"?
int03e
Фронт может заниматься своим прямым делом — написанием фронта. Почему я, как бек девелопер, не могу посмотреть дизайн в фигме, и потом отдать фронту готовое апи с достаточными и не излишними данными? А если у нас при этом еще и GraphQL, то вопрос underfetching / overfetching решается сам по себе вообще.
breslavsky Автор
Насколько бекенд разработчик хорошо может разбираться в UI, что бы по нему сделать качественный API?
int03e
Я не хочу кидаться шапками и говорить «да фигня ваш фронт», но я не совсем понимаю вопрос — что значит «разбираться в UI»? Вот я смотрю дизайн, вижу что там есть условный дропдаун с выбором customer name — значит, фронту нужен customer name и customer id. Бывают более сложные случаи, конечно, если я в чем-то не уверен — консультируюсь с фронтендерами, они высказывают свои пожелания и я их учитываю. Но, в любом случае, проектирование API — это задача бекенда. В конце концов, это самое API может использоваться приложением на реакте, мобильными приложениями iOS и Android, а еще оно напрямую может использоваться клиентами как public API. И условный frontend react developer будет в этом понимать больше чем бекендер? Почему?
breslavsky Автор
Как вы считаете, а так будет лучше для Вас как для бэка?
И бэку не нужно залезать в Фигму, лазить по экранам, разбираться во всей UX/UX специфике приложения.
int03e
Нет, не будет лучше. Фронт — это всего-лишь клиент к бекенду. И я этим не пытаюсь унизить фронт, не поймите неправильно — я вполне себе могу представить ситуацию, когда логики и даже алгоритмов там больше чем на бекенде (какая-нибудь онлайн версия фотошопа, например). Но фронт остается клиентом, и (потенциально) одним из многих клиентов. web UI, iOS app, Android app… Для каждого делать отдельный API? Может в этом и есть смысл, но чаще его нет. И кого же мне слушать — реакт девелопера Васю, свифт девелопера Колю, или же котлин девелопера Ваню? У всех у них свои пожелания к API, у всех у них разный интерфейс. Поэтому проектировать API (а это часть бекенда) должны на бекенде. Учитывая желания разработчиков консьюмеров этого самого API, конечно же.
nin-jin
Достаточно через любую систему контроля версий согласвать схему предметной обасти и всё:
И не надо для каждой сущности изобретать свой протокол взаимодействия да ещё и прибитый гвоздями к HTTP.
mvv-rus
Или, может быть — схему модели представления? А то в предметной области может много ещё чего лишнего быть. Например, показывать покупателю в интернет-магазине склад и логистику этого магазина — это лишнее, наверное, не так ли?
nin-jin
Покупателю - лишнее, а вот менеджеру уже нет.
mvv-rus
А менеджер — он что, тоже тем же приложением, со всей тамошней рекламой и кликбейтами пользоваться будет?
А ведь еще есть маркетологи (это — про клики, просмотры до конца и воронку). И бухгалтеры (это — про счета деньги).
Короче, подумайте над моим предложением. Я не призываю делать его универсальным принципом, я предлагаю его как вариант для некоторых случаев. И — над предложением автора статьи для таких случаев: все-таки фронэндеры нередко оказываются на переднем крае и первыми узнают про хотелки пользователей, не так ли? А тогда логично, чтобы за модель представления (и базирующемся на ней API) отвечали они, коли уж в штатном расписании аналитик не предусмотрен.
nin-jin
Конечно, чтобы понимал, что пользователю этот кликбейт с рекламой не в тему тоже не упёрлись. Но даже для разных UI вовсе не нужно делать разный API - достаточно сделать нормальную систему прав, которая нужна в любом случае.
breslavsky Автор
Не подскажите что формат описания?
nin-jin
Chineese
Есть обратный случай, когда бэк тривиален и состоит из CRUD и перекладывания JSON между БД и фронтом, для реализации такого есть даже кодогенерация из swagger-файлов.
Почему бы в таком случае не воспользоваться?
breslavsky Автор
Но ведь Swagger это же не про генерацию. Я ведь писал:
Не ужели это не так?