Идея написать данную статью у меня возникла в самый обычный рабочий день, в момент когда ко мне от менеджеров в jira упала новая задачка. Сама задача была нормально заполнена - было и подробное описание, и ссылка на документацию с бизнес-требованиями, и приложены макеты.
Однако, её статус был не в “Ready for development”. Также можно было увидеть что сама задача ждёт выполнения другой задачи - на разработку API с данными. Здесь у меня начались вопросы, а также желание в очередной раз разъяснить менеджерам что критичных блокеров у этой задачи нет.
За годы службы фронтенд-разработчиком могу уверенно сказать что одна из достаточно часто встречающихся проблем в рабочем процессе команд веб-разработки - это неправильно построенная коммуникация между фронтенд и бэкенд разработчиками, не до конца разделенные между ними сферы ответственности, и в целом пуск деятельности на самотек, “авось как-нибудь сработаются, главное чтобы в конце нормальный продукт получился”. При том что внутрикомандные практики взаимодействия между разработчиками в большинстве компаний в целом отлажены, взаимодействию межкомандному уделяется гораздо меньше времени, что странно, учитывая, что работают они зачастую над одним и тем же продуктом.
Одной из частностей этой общей проблемы является то, что в большинстве мест где я работал, толком была не распараллелена работа между бэкенд и фронтенд разработчиками. И даже если макеты готовы и сама фича “от и до” проанализирована со стороны системных аналитиков, то есть уже понятно что нужно получить на выходе - команде фронтенд-разработки все-равно надо дождаться работающей апишки прежде чем приступить к работе. Причем такая ситуация стабильно не меняется с годами, и отсутствие готовой серверной части фичи по-умолчанию является блокером для работы команды клиентской разработки.
Я встречал даже абсурдные ситуации. Так, в одном из стартапов, менеджер в связи с большой загруженностью бэкэндеров и нарушением ими дедлайнов фактически дал команде фронтов пару дней отдыха, мол негоже писать фронт пока бэка нет, по-началу к большой моей радости конечно же. Радость быстро улетучилась, когда тот же менеджер по происшествию этих дней сказал что придётся на работу выходить в субботу, ибо апишки уже готовы, а фронтовые задачи еще не паханные. Разумеется следующие несколько недель-месяцев я недовольно ворчал, что все всё делают не так, и никакая апишка фронтендеру не нужна для того чтобы написать работающий фронт.
Да, если на момент начала вашей работы над клиентской логикой уже есть готовое REST-api со всеми необходимыми Вам данными, то это идеальный вариант без подводных камней. Но отсутствие онных - это отнюдь не блокер.
Особенно остро хочется подсветить данный вопрос если у Вас не монолит, а например SPA - приложение, обращающееся за данными к внешнему API. В данном случае, ваше клиентское приложение и API к которому оно ходит за данными - это формально две разных программы и в принципе связанности между ними не должно быть никакой, то есть при проектировании вашего SPA-приложения нужно сразу проектировать приложение так, чтобы переезд на другую версию API не представлял особых проблем, а слои данных должны быть отделены от слоев представления.
Распараллелить задачи клиентской и серверной разработки Вам поможет техника мокинга данных - использования смоделированных данных, имитирующих реальные. Данная техника наиболее широко используется в тестировании, но и в разработке находит широкое применение.
Конкретные инструменты для мокинга мы рассмотрим чуть дальше, а пока перейдём к организации процесса разработки фронтенда при отсутствии реальных данных или с отсутствием доступа к онным.
Как построить работу над задачей, если у Вас еще нет готовых данных
Тут многое зависит от того как построены рабочие процессы в вашей команде. Самый хороший вариант - когда Вы уже заранее знаете как будет выглядеть апишка с вашими данными и что в ней будет приходить.
Это бывает в тех случаях, когда:
Уже есть ТЗ на бэкенд или документация, с четким описанием работы API, где есть как урл запроса, так и полностью описаны возвращаемые данные, с типами и названиями ключей. Такое часто бывает в командах где есть системные аналитики, которые детально описывают как выглядит и должна работать программа. Это идеальный вариант, подход “написал и забыл”, с бэкендерами можно даже и не взаимодействовать, всё по ТЗ.
Вы оговорили контракт с бэкэндом-разработчиком. Встретились/созвонились, оговорили какое содержание будет в ответе на запрос, закрепили где-то письменно в жире/конфлюенсе/постмане и готово.
Если же по какой-то причине, структура, содержание и форма API с данными Вам неизвестны, и согласовать его не представляется возможности, то это тоже не повод откладывать разработку клиентского приложения.
Если у Вас есть дизайн-макет и бизнес-требования к фиче от аналитиков, то содержимое API вполне можно понять по дизайн-макету разрабатываемой фичи и её описанию. Единственным нюансом здесь является то, что после того как работа над API со стороны бэкенд-разработки завершится, вам нужно будет адаптировать ваш код заточенный на работу с замоканными данными на данные реальные. Важный момент: так как мы не знаем точного содержания api, то всю работу с ней мы изолируем в специально предназначенном для этого контроллере-адаптере, который на выходе отдает всегда один и тот же набор данных как при работе с замоканной апи - до того как станет известно содержание реального апи; так и после того как мы получили в руки боевую апишку. Делается это для того чтобы мы не растаскивали данные по всему приложению, что приводит к тому что миграция на другую апи становится более трудоемкой.
Давайте теперь вкратце рассмотрим основные инструменты для мокинга данных.
Инструменты и способы мокинга данных
Инструменты, интегрирующиеся непосредственно в ваше фронтенд‑приложение.
Здесь перечислены инструменты, которые устанавливаются как npm‑зависимости к вашему frontend‑приложению и в нем же настраиваются/кастомизируются.
Библиотека, использующая в своей основе PretenderJS. Pretender работает при помощи monkey-patching браузерных имплементаций XMLHttpRequest и fetch. В результате вызов данных браузерных api в браузере ведёт в определенный вами контроллер откуда и отдаются замоканные данные. Сама Mirage.JS просто добавляет вокруг этого функционала довольно объемное API для работы с слоем данных, например, in-memory базу данных, ORM и модели данных для решения проблемы связанных данных. Причем, при перезагрузке страницы в браузере база данных будет сброшена. На сервере, если вдруг на вашем проекте используется ssr, работать не будет. Поддержки GraphQL из коробки нет. Поддержки веб-сокетов нет. Также из минусов хочется отметить, что запросы не появляются во вкладке Network в инструментах разработчика браузера, а также что сама библиотека имеет довольно низкую степень поддержки авторами.
Данный инструмент для мокинга API в своей основе использует сервис-воркеры. Со стороны браузера выполнение запросов выглядит нативно (по-крайней мере запросы отображаются во вкладке Network). Библиотека позволяет выполнение запросов со стороны сервера, есть встроенная поддержка GraphQL. Поддержки веб-сокетов нет. Встроенный API для работы с моделями данных как в MirageJS отсутствует, но данную функциональность можно добавить дополнительными библиотеками от авторов.
В отличии от предыдущих, данный инструмент поднимает настоящий сервер на машине разработчика, чем отличается от предыдущих указанных мной инструментов. JSON Server имеет довольно мощный работающий функционал из коробки: полностью работающий REST-api с чтением, добавлением и удалением записей из базы данных, основанной на json-файлах, а также встроенной возможности фильтрации, пагинации и сортировки данных. И хотя с одной стороны JSON.server предоставляет довольно мощный объем функционала из коробки, - кастомизации к этому делу приложено не было, а соответственно, к замене вашей боевой API данный инструмент мало подходит. Зато отлично подходит для создания прототипов, учебных материалов, и других ситуаций когда вам быстро нужен сервер с наиболее базовым функционалом без возможности расширения/кастомизации.
Я опробовал все вышеперечисленные инструменты, и они неплохо справляются со своей основной функцией. Однако, что меня смутило в процессе использования, так это сам подход, а конкретно то, что они устанавливаются как зависимости на ваш проект, и меняют его исходники. Да, это dev-dependency. Однако в моей практике у меня все-равно возникли проблемы с отделом информационной безопасности в компании где я работал, - из-за потенциальной npm-уязвимости одного из вышеуказанных инструментов при попытке добавить его как “фичу” в следующий релиз.
Postman.
Postman в нынешнее время - незаменимый инструмент, и не только для бэкенд разработчиков с тестировщиками. Фронтендеры его используют как документацию и для обращения к замоканному апи. У постмана есть ready-to-use функция поднятия сервера с мок-апи в облаке, к которой можно обращаться с любого клиента и получать в ответ заглушки, которые были написаны вами там же. К инструментам документирования с возможностью поднятия мок-сервера также можно отнести и Swagger, но опробовать в бою его не успел.
BFF.
Если на вашем проекте используется подход Backend-For-Frontend, то это идеальное место для того чтобы определить в нем отдачу захардкоженных данных по заранее определенной логике. Однако, поскольку это все же боевой сервер, а не вспомогательный сервис для девелоперских нужд, у него есть свои ограничения, и ничего более серьезного чем отдать захардкоженный json я бы в нем делать не рекомендовал.
Самописное решение.
Лично для меня наиболее функциональным и простым вариантом оказалось поднятие своего node.js сервера на базе Express/Koa. Во-первых, это настоящий сервер, а не его имитация. А также какое-никакое отделение функционала отдачи фейковых данных от бизнес-логики вашего приложения. Во-вторых, это отсутствие ограничений, можно реализовать все что вам нужно: кэширование, проксирование на боевое апи, добавление легкой базы данных, возможность работы как с сокетами, так и с http-запросами, возможность отдачи статики, генерация картинок по запросу и в принципе все, на что хватит вашей фантазии.
Именно с необходимостью генерации картинок (с надписью, фоном и определенного заданного размера) я столкнулся, когда во времена локдауна, безопасники закрыли удаленщикам доступ вообще ко всем серверам со статикой. И именно выручило то, что у нас уже был готовый к использованию локальный сервис для отдачи замоканных данных, функционал которого был легко расширяем.
А какие инструменты для мокинга данных используете Вы? Буду рад дополнениям и обсуждению в комментариях.
Заключение
Мы рассмотрели основные подходы к мокингу данных, которые я успешно применяю в своей работе не протяжении многих лет, а также ознакомились со всем многообразием инструментов, которые могут нам помочь в этом.
Основная цель данной статьи - чтобы как можно большее количество разработчиков и менеджеров осознала и приняла как факт, что разработку как фронтенда так и бэкенда можно (и иногда нужно) осуществлять параллельно, не ожидая друг друга. Если в вашей команде до сих пор фронт работает только на боевых данных, то обязательно оповестите ваших менеджеров и команду о том, что возможность не ждать готовый бэк для разработки клиентской части СУЩЕСТВУЕТ. Это поможет менеджменту в планировании будущих фич, а Вам поможет начинать работать над задачами раньше и в спокойном режиме, а не в поте лица в режиме аврала.
Буду рад обратной связи в комментариях, заранее спасибо.
Комментарии (7)
SergeiZababurin
02.11.2024 08:32Я для решения описанных проблем использую mocha puppeteer debug remote ws chrome open api.
Начинаю в каких то моментах с кода, в каких то моментах с тестов. Разницы никакой, потому что код один и тот же.
pvzh
02.11.2024 08:32Postman в нынешнее время - незаменимый инструмент, и не только для бэкенд разработчиков с тестировщиками.
Postman это ненасытный монстр, который нас всех проглотит;) Так ли уж незаменим? Если не секрет, как вы коллекции храните и распространяете? Возможно, есть платная подписка. Меня смущает привязка к облаку и возможность блокировки. Больше нравится примеры запросов хранить текстом в репозитории, в виде файлов, как это делают httpYac или Bruno.
А мок сервер наверняка можно отдельно поднять, из OpenAPI-схемы. Такой подход видится более гибким и надёжным.
gen1lee
02.11.2024 08:32А чем плоха просто папка с json файлами ответов, которые возвращаются в апи методах вместо fetch к серверу, с задержкой, и которую можно использовать в тестах, не поднимая никаких серверов?
aleksand44 Автор
02.11.2024 08:32Ничем не плоха если Вам её достаточно, но если есть также задача обработать ошибки вызванные статусами 4хх и 5хх, то тут уже надо что-то посерьёзнее.
atomr_mf
02.11.2024 08:32Использую на работе MSW, с всеми задачами справляется, все покрывает. Но было интересно почитать про другие инструменты, спасибо
pvzh
Долгое основательное вступление, к нему ожидались поучительные примеры из жизни, но нет, опять в другой раз. Сама то идея понятна и привлекательна. Хочется узнать реальный опыт, вот собрали OpenAPI схему, утвердили, положили в репозиторий, таким-то инструментом нагенерили моки, оживили их, фронтэндеры пользуются. Потом прилетела правка, обновили схему. Что-то ещё надо сделать? Насколько гладко и безболезненно проходят правки? В моей практике есть задачи, где такие правки неоднократные, хотя и мелкие.
aleksand44 Автор
Понимаю, данную публикацию изначально планировал на "entry" уровне, просто как призыв к действию и краткий обзор имеющихся инструментов. Про опыт конкретных реализаций наверное в следующих публикациях расскажу, благо он есть.
Если правки не меняют логику работы клиентского приложения, а только касаются формата API, то изменения гладко проходят. Используем что-то типа паттерна "Адаптер", который на вход принимает схему данных приходящую из api, а на выходе отдаёт схему данных необходимую для построения UI (её можно даже просто видя макет определить). Соответственно, если макеты не менялись то на выходе адаптер отдаёт всегда одно и тоже, и при небольших правках в api, мы просто учим адаптер работать с новыми входящими данными. Выглядит это обычно как правки в пару строк в одном файле, то есть безболезненно. Особенно если у вас моки автоматом генерятся.