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

Однако, её статус был не в “Ready for development”. Также можно было увидеть что сама задача ждёт выполнения другой задачи - на разработку API с данными. Здесь у меня начались вопросы, а также желание в очередной раз разъяснить менеджерам что критичных блокеров у этой задачи нет.

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

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

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

Да, если на момент начала вашей работы над клиентской логикой уже есть готовое REST-api со всеми необходимыми Вам данными, то это идеальный вариант без подводных камней. Но отсутствие онных - это отнюдь не блокер.

Особенно остро хочется подсветить данный вопрос если у Вас не монолит, а например SPA - приложение, обращающееся за данными к внешнему API. В данном случае, ваше клиентское приложение и API к которому оно ходит за данными - это формально две разных программы и в принципе связанности между ними не должно быть никакой, то есть при проектировании вашего SPA-приложения нужно сразу проектировать приложение так, чтобы переезд на другую версию API не представлял особых проблем, а слои данных должны быть отделены от слоев представления.

Распараллелить задачи клиентской и серверной разработки Вам поможет техника мокинга данных - использования смоделированных данных, имитирующих реальные. Данная техника наиболее широко используется в тестировании, но и в разработке находит широкое применение.

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

Как построить работу над задачей, если у Вас еще нет готовых данных

Тут многое зависит от того как построены рабочие процессы в вашей команде. Самый хороший вариант - когда Вы уже заранее знаете как будет выглядеть апишка с вашими данными и что в ней будет приходить.

Это бывает в тех случаях, когда:

  1. Уже есть ТЗ на бэкенд или документация, с четким описанием работы API, где есть как урл запроса, так и полностью описаны возвращаемые данные, с типами и названиями ключей. Такое часто бывает в командах где есть системные аналитики, которые детально описывают как выглядит и должна работать программа. Это идеальный вариант, подход “написал и забыл”, с бэкендерами можно даже и не взаимодействовать, всё по ТЗ.

  1. Вы оговорили контракт с бэкэндом-разработчиком. Встретились/созвонились, оговорили какое содержание будет в ответе на запрос, закрепили где-то письменно в жире/конфлюенсе/постмане и готово.

Если же по какой-то причине, структура, содержание и форма API с данными Вам неизвестны, и согласовать его не представляется возможности, то это тоже не повод откладывать разработку клиентского приложения.

Если у Вас есть дизайн-макет и бизнес-требования к фиче от аналитиков, то содержимое API вполне можно понять по дизайн-макету разрабатываемой фичи и её описанию. Единственным нюансом здесь является то, что после того как работа над API со стороны бэкенд-разработки завершится, вам нужно будет адаптировать ваш код заточенный на работу с замоканными данными на данные реальные. Важный момент: так как мы не знаем точного содержания api, то всю работу с ней мы изолируем в специально предназначенном для этого контроллере-адаптере, который на выходе отдает всегда один и тот же набор данных как при работе с замоканной апи - до того как станет известно содержание реального апи; так и после того как мы получили в руки боевую апишку. Делается это для того чтобы мы не растаскивали данные по всему приложению, что приводит к тому что миграция на другую апи становится более трудоемкой.

Ваши методы для получения данных всегда должны отдавать данные одного вида, неважно получены они из боевого или замоканного API
Ваши методы для получения данных всегда должны отдавать данные одного вида, неважно получены они из боевого или замоканного API

Давайте теперь вкратце рассмотрим основные инструменты для мокинга данных.

Инструменты и способы мокинга данных

  1. Инструменты, интегрирующиеся непосредственно в ваше фронтенд‑приложение.

Здесь перечислены инструменты, которые устанавливаются как npm‑зависимости к вашему frontend‑приложению и в нем же настраиваются/кастомизируются.

Mirage.js

Библиотека, использующая в своей основе PretenderJS. Pretender работает при помощи monkey-patching браузерных имплементаций XMLHttpRequest и fetch. В результате вызов данных браузерных api в браузере ведёт в определенный вами контроллер откуда и отдаются замоканные данные. Сама Mirage.JS просто добавляет вокруг этого функционала довольно объемное API для работы с слоем данных, например, in-memory базу данных, ORM и модели данных для решения проблемы связанных данных. Причем, при перезагрузке страницы в браузере база данных будет сброшена. На сервере, если вдруг на вашем проекте используется ssr, работать не будет. Поддержки GraphQL из коробки нет. Поддержки веб-сокетов нет. Также из минусов хочется отметить, что запросы не появляются во вкладке Network в инструментах разработчика браузера, а также что сама библиотека имеет довольно низкую степень поддержки авторами.

Mock Service Worker (MSW)

Данный инструмент для мокинга API в своей основе использует сервис-воркеры. Со стороны браузера выполнение запросов выглядит нативно (по-крайней мере запросы отображаются во вкладке Network). Библиотека позволяет выполнение запросов со стороны сервера, есть встроенная поддержка GraphQL. Поддержки веб-сокетов нет. Встроенный API для работы с моделями данных как в MirageJS отсутствует, но данную функциональность можно добавить дополнительными библиотеками от авторов.

JSON Server

В отличии от предыдущих, данный инструмент поднимает настоящий сервер на машине разработчика, чем отличается от предыдущих указанных мной инструментов. JSON Server имеет довольно мощный работающий функционал из коробки: полностью работающий REST-api с чтением, добавлением и удалением записей из базы данных, основанной на json-файлах, а также встроенной возможности фильтрации, пагинации и сортировки данных. И хотя с одной стороны JSON.server предоставляет довольно мощный объем функционала из коробки, - кастомизации к этому делу приложено не было, а соответственно, к замене вашей боевой API данный инструмент мало подходит. Зато отлично подходит для создания прототипов, учебных материалов, и других ситуаций когда вам быстро нужен сервер с наиболее базовым функционалом без возможности расширения/кастомизации.

Я опробовал все вышеперечисленные инструменты, и они неплохо справляются со своей основной функцией. Однако, что меня смутило в процессе использования, так это сам подход, а конкретно то, что они устанавливаются как зависимости на ваш проект, и меняют его исходники. Да, это dev-dependency. Однако в моей практике у меня все-равно возникли проблемы с отделом информационной безопасности в компании где я работал, - из-за потенциальной npm-уязвимости одного из вышеуказанных инструментов при попытке добавить его как “фичу” в следующий релиз.

  1. Postman.

Postman в нынешнее время - незаменимый инструмент, и не только для бэкенд разработчиков с тестировщиками. Фронтендеры его используют как документацию и для обращения к замоканному апи. У постмана есть ready-to-use функция поднятия сервера с мок-апи в облаке, к которой можно обращаться с любого клиента и получать в ответ заглушки, которые были написаны вами там же. К инструментам документирования с возможностью поднятия мок-сервера также можно отнести и Swagger, но опробовать в бою его не успел.

  1. BFF.

Если на вашем проекте используется подход Backend-For-Frontend, то это идеальное место для того чтобы определить в нем отдачу захардкоженных данных по заранее определенной логике. Однако, поскольку это все же боевой сервер, а не вспомогательный сервис для девелоперских нужд, у него есть свои ограничения, и ничего более серьезного чем отдать захардкоженный json я бы в нем делать не рекомендовал.

  1. Самописное решение.

Лично для меня наиболее функциональным и простым вариантом оказалось поднятие своего node.js сервера на базе Express/Koa. Во-первых, это настоящий сервер, а не его имитация. А также какое-никакое отделение функционала отдачи фейковых данных от бизнес-логики вашего приложения. Во-вторых, это отсутствие ограничений, можно реализовать все что вам нужно: кэширование, проксирование на боевое апи, добавление легкой базы данных, возможность работы как с сокетами, так и с http-запросами, возможность отдачи статики, генерация картинок по запросу и в принципе все, на что хватит вашей фантазии.

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

А какие инструменты для мокинга данных используете Вы? Буду рад дополнениям и обсуждению в комментариях.

Заключение

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

Основная цель данной статьи - чтобы как можно большее количество разработчиков и менеджеров осознала и приняла как факт, что разработку как фронтенда так и бэкенда можно (и иногда нужно) осуществлять параллельно, не ожидая друг друга. Если в вашей команде до сих пор фронт работает только на боевых данных, то обязательно оповестите ваших менеджеров и команду о том, что возможность не ждать готовый бэк для разработки клиентской части СУЩЕСТВУЕТ. Это поможет менеджменту в планировании будущих фич, а Вам поможет начинать работать над задачами раньше и в спокойном режиме, а не в поте лица в режиме аврала.

Буду рад обратной связи в комментариях, заранее спасибо.

Комментарии (7)


  1. pvzh
    02.11.2024 08:32

    Долгое основательное вступление, к нему ожидались поучительные примеры из жизни, но нет, опять в другой раз. Сама то идея понятна и привлекательна. Хочется узнать реальный опыт, вот собрали OpenAPI схему, утвердили, положили в репозиторий, таким-то инструментом нагенерили моки, оживили их, фронтэндеры пользуются. Потом прилетела правка, обновили схему. Что-то ещё надо сделать? Насколько гладко и безболезненно проходят правки? В моей практике есть задачи, где такие правки неоднократные, хотя и мелкие.


    1. aleksand44 Автор
      02.11.2024 08:32

      Долгое основательное вступление, к нему ожидались поучительные примеры из жизни, но нет, опять в другой раз. Сама то идея понятна и привлекательна. Хочется узнать реальный опыт

      Понимаю, данную публикацию изначально планировал на "entry" уровне, просто как призыв к действию и краткий обзор имеющихся инструментов. Про опыт конкретных реализаций наверное в следующих публикациях расскажу, благо он есть.

      собрали OpenAPI схему, утвердили, положили в репозиторий, таким-то инструментом нагенерили моки, оживили их, фронтэндеры пользуются. Потом прилетела правка, обновили схему. Что-то ещё надо сделать? Насколько гладко и безболезненно проходят правки?

      Если правки не меняют логику работы клиентского приложения, а только касаются формата API, то изменения гладко проходят. Используем что-то типа паттерна "Адаптер", который на вход принимает схему данных приходящую из api, а на выходе отдаёт схему данных необходимую для построения UI (её можно даже просто видя макет определить). Соответственно, если макеты не менялись то на выходе адаптер отдаёт всегда одно и тоже, и при небольших правках в api, мы просто учим адаптер работать с новыми входящими данными. Выглядит это обычно как правки в пару строк в одном файле, то есть безболезненно. Особенно если у вас моки автоматом генерятся.


  1. SergeiZababurin
    02.11.2024 08:32

    Я для решения описанных проблем использую mocha puppeteer debug remote ws chrome open api.
    Начинаю в каких то моментах с кода, в каких то моментах с тестов. Разницы никакой, потому что код один и тот же.


  1. pvzh
    02.11.2024 08:32

    Postman в нынешнее время - незаменимый инструмент, и не только для бэкенд разработчиков с тестировщиками.

    Postman это ненасытный монстр, который нас всех проглотит;) Так ли уж незаменим? Если не секрет, как вы коллекции храните и распространяете? Возможно, есть платная подписка. Меня смущает привязка к облаку и возможность блокировки. Больше нравится примеры запросов хранить текстом в репозитории, в виде файлов, как это делают httpYac или Bruno.

    А мок сервер наверняка можно отдельно поднять, из OpenAPI-схемы. Такой подход видится более гибким и надёжным.


  1. gen1lee
    02.11.2024 08:32

    А чем плоха просто папка с json файлами ответов, которые возвращаются в апи методах вместо fetch к серверу, с задержкой, и которую можно использовать в тестах, не поднимая никаких серверов?


    1. aleksand44 Автор
      02.11.2024 08:32

      Ничем не плоха если Вам её достаточно, но если есть также задача обработать ошибки вызванные статусами 4хх и 5хх, то тут уже надо что-то посерьёзнее.


  1. atomr_mf
    02.11.2024 08:32

    Использую на работе MSW, с всеми задачами справляется, все покрывает. Но было интересно почитать про другие инструменты, спасибо