Сегодня разберёмся с запросами и состояниями экрана раз и навсегда. На примере ресторана узнаем, как приложение общается с сервером и как процессы на бэкенде влияют на интерфейс.

Чек-лист по состояниям экрана ждёт вас в конце статьи.

Когда дизайнер проектирует что-то сложнее посадочной страницы, возникает необходимость в разных состояниях экранов. Чаще всего дизайнеры получают одни и те же правки: «Тут нужен лоадер» или «Как выглядит ошибка?». Полный набор состояний никогда не появляется без пинка аналитика.

Годами я наблюдаю бессмысленный пинг-понг. Дизайнер рисует экран и ждёт ревью. Аналитик через пол дня открывает ссылку и просит дорисовать состояние загрузки. Задачка висит в статусе «ин-прогресс» и не уходит в разработку. Сроки растягиваются, релизы переносится.

Классическая переписка дизайнера с аналитиком
Классическая переписка дизайнера с аналитиком

Проблема в том, что никто не объяснил дизайнерам, как приложение работает с данными, и как подкапотные процессы влияют на элементы интерфейса.

Этот материал для всех, кто проектирует цифровые продукты и сложные сайты. Аналитики и менеджеры, покажите статью своим дизайнерам.

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

Что в статье:

  1. Как приложение общается с сервером на примере ресторана

  2. Откуда появляется контент?

  3. Последовательные и параллельные запросы

  4. Синхронные и асинхронные запросы

  5. Обязательные и необязательные запросы

  6. Пагинация и пустое состояние — когда нужны?

  7. Ошибки: какие бывают?

  8. Добавление и удаление элементов — на фронте или на бэке?

  9. Как кэш влияет на загрузку?

  10. Подарок: чек-лист по состояниям интерфейса

Клиент-серверная архитектура для чайников

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

Клиент-серверная архитектура в упрощённом виде
Клиент-серверная архитектура в упрощённом виде

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

Архитектура на примере ресторана

Представьте, что приложение — это ресторан.

Как «пользователь» ресторана вы взаимодействуете с собственным столиком, меню и официантом. Гостевой зал — это клиент. В зале красивый интерьер, меню написано аккуратным шрифтом, а на столе заранее стоят соль с перцем и салфетки.

Вы заказываете карбонару. Официант мог бы сварить пасту прямо у вас на столе, параллельно натирая пармезан и обжаривая бекон. Такому заведению потребовалось бы 20 многоруких официантов и столы со встроенной электроплиткой. В нашем примере ресторан более менее стандартный, поэтому официант передаёт ваш заказ на кухню. Кухня — это сервер.
«Одна карбонара с двойным пармезаном» — это запрос.

Клиент-серверная архитектура на примере ресторана
Клиент-серверная архитектура на примере ресторана

Через минуту вы подзываете второго официанта и заказываете салат. Теперь два блюда готовятся параллельно. В каких-то ресторанах еду выносят в порядке готовности, в других — салат строго первым курсом.

Пока блюда готовятся, официант расчищает место на столе, ставит приборы и хлебную корзинку. Такое состояние стола как бы говорит: «Здесь скоро будет еда».

Не все блюда одинаково важны. Если кухня не приготовит салат, вы не расстроитесь. Салат — необязательное блюдо. Однако без пасты ваш обед не состоится. Паста — обязательная.

Ресторан не может приготовить любое блюдо. Вот вы просите креветки в яблочном уксусе, официант консультируется с шеф-поваром и возвращается с ответом: «Такое у нас не подают, извините» — это ошибка пользователя. А бывает, заказываешь «Цезарь» из меню, и через 15 минут выясняется, что на кухне закончились чесночные гренки. Это уже ошибка сервера.

Приложения и рестораны спроектированы людьми для людей. Процессы внутри цифрового сервиса не сильно отличаются по логике от сервиса ресторанного. Давайте теперь перейдём к интерфейсу.

Откуда взялся контент

Для начала нам необходимо понять, нужны ли странице дополнительные состояния.

Пользователь видит блоки интерфейса, наполненные контентом — текстами, картинками и видосами. Каждый блок интерфейса и каждый кусок контента — это либо хардкод, либо данные с сервера.

Хардкод — это когда программист зафиксировал элемент в коде программы. Если текст или иллюстрация хардкодная, то её содержимое неизменно. Дизайнер может расслабиться — ни о каких состояниях тут думать не надо.

скриншот кнопки приложение ВкусВилл
Скриншот приложения ВкусВилла

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

Если данные на странице не хардкодные, значит требуются дополнительные состояния — загрузки, ошибки или отсутствия контента.

Последовательные и параллельные запросы

Как только мы поняли, откуда берутся данные на экране, нужно задать аналитику вопрос: «Какие здесь отправляются запросы?»

Последовательные запросы — это когда блоки экрана загружаются один за другим. Состояние каждого следующего блока зависит от состояния предыдущего. Пока все процессы не отработают, процесс не завершён, ведь данные взаимосвязаны. Последовательные запросы чаще всего отправляются при инициализации экрана.

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

последовательный запрос иллюстрация
Пример последовательного запроса в интерфейсе

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

Пример: Гугл. Один блок загружается, а другие уже доступны.

гугл поиск блоки контента
Скриншот из Гугл-поиска

Синхронные и асинхронные запросы

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

авторизация скриншот
Авторизация в приложении Fresha

Асинхронные запросы превращают пользовательский опыт в кайф. Ничего не блокируется, и пользователь продолжает свободно пользоваться интерфейсом. Социальная сеть «Вконтакте» стала успешной во многом благодаря внедрению асинхронных AJAX-запросов.

телеграм реакция на сообщение
Лайк — простейший пример асинхронного запроса

Обязательные, необязательные и фоновые запросы

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

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

полноэкранная ошибка скриншот
Полноэкранная ошибка

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

Ютуб загрузка рекомендаций
«Похожие видео» на Ютубе не загружаются, остальной интерфейс доступен

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

Пример: не получилось загрузить историю.

Инстаграм ошибка загрузки истории
Снек-ошибка при загрузке сториз

Пагинация и пустое состояние

Почти любая коллекция контента — фотки в инсте, проекты в Фигме, видосы на Ютубе — подгружается порциями. В противном случае пришлось бы грузить тысячи единиц контента за раз, и мы бы никогда не дождались окончания загрузки.

Каждая новая пачка контента начинает загружаться по триггеру. Пользователь промотал экран с фоточками до конца — нужно показать ему ещё. Отправляем запрос на ещё 10 фотографий.

Пагинация подразумевает состояние загрузки в том месте, где пользователь ожидает увидеть новый контент. Дизайнер может пойти простым путём и использовать стандартный спиннер. Более продвинутые ребята показывают схематичные прямоугольники и кружочки, которые говорят: «мы тут придерживаем местечко для чего-то более интересного».

В примере ниже мы видим одновременно пагинацию — колёсико загрузки — и отдельный запрос на обложки для видео, которые сейчас представлены серыми прямоугольниками — скелетонами. Это два параллельных необязательных запроса.

ютуб видео загрузка
Шиммеры на превьюшках юутб-видео и лоадер пагинации

Дизайнеру всегда следует помнить, что контента может и не быть. Пользователь мог не успеть добавить товары в «Избранное» или не начал ни одной переписки в «Мессенджере».

Пустое состояние (англ. Empty State) говорит юзеру: «Здесь пока пусто, добавь что-нибудь». Можем показать эмпти-стейт после загрузки, а можем — моментально, если знаем заранее, что контент отсутствует.

Пустое состояние интерфейса
Эмпти-стейт в приложении Rakuten

Pull-to-Refresh — это когда пользователь тянет экран мобильного приложения вниз для перезагрузки. ПТР отправляет запросы на обновление всех данных на экране.

Пример: все графики на кадшборде обновляются одним ПТР-ом.

pull-to-refresh птр-лоадер
Pull-to-Refresh в приложении MacroFactor

Ошибки: типичные и специфические

Ошибки бывают типовые и специфические. Разобраться со первыми вам поможет аналитик или разработчик, а мы в рассмотрим несколько базовых.

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

Не нужно перекрывать экран при каждом обрыве связи. Соединение возобновится через 10 секунд, а терпение юзера — нет. Чатик в Телеграме или маршрут в Яндекс Гоу информируют о состоянии сети маленькой подписью.

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

Тайм-аут. Запросу выделяется фиксированное время на отправку, обычно 10–15 секунд. Если запрос не отработал в указанное время, приложение может отправить его повторно «за кулисами», либо сообщить о проблеме юзеру. В первом случае можем написать, что процесс выполняется дольше обычного. Во втором случае дизайнер рисует состояние с кнопкой повторной отправки.

Ошибки валидации. Каждая форма проверяется скриптом на правильность заполнения. Если пользователь не заполнил обязательное поле, либо заполнил его неверными данными, интерфейс должен об этом сообщить.

Удаление и добавление элементов

Добавление, удаление и изменение порядка элементов проходит либо на клиенте, либо на сервере. От этого зависит, в какой момент покажем загрузку.

Если редактирование медиафайлов происходят на клиенте, даём юзеру полную свободу — пусть играется с картинками беспрепятственно. Потребуется одно состояние загрузки — в момент сохранения.

редактирование фотографий
Bumble меняет порядок фотографий на клиенте

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

Не забываем про состояния ошибок. Рисуем их по одной логике с лоадерами.

Кэширование

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

Пример. Лента Инсты кэшируется. Телефон хранит фотки с прошлой сессии. Пользователь открывает приложение и вместо серых квадратиков видит реальные фотографии. Фоном идёт запрос новой пачки контента.

инстаграм интерфейс фото обуви
Мы ещё не загрузили аватарку, но уже видим фотку из кэша

Дизайнеру нужно продумать все возможные сценарии:
— Сколько постов хранить в кэше?
— Что будет, когда пользователь долистает список до конца?
— Как покажем проблемы с интернетом?
— Куда подвинем старые фотографии в момент получения новых?
— Нужно ли промежуточное состояние загрузки?
— Что будет, если пользователь попробует обновить экран самостоятельно?
— …

Подытожим

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

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

Подарок

Собрал чек-лист по состояниями интерфейса. Простой список поможет проверить макеты на наличие необходимых экранов. Документ можно пошерить младшим дизайнерам, чтобы не писать по десять комментов к каждой задачке.

Чек-лист лежит в моём телеграм-канале. Забирайте, пока бесплатно.

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


  1. Blaga
    18.11.2024 20:27

    Не знаю, где вы находите таких дизайнеров... но хорошие продуктовые и ux дизайнеры все это знают и прорабатывают и без аналитиков.


  1. VZ1
    18.11.2024 20:27

    Несомненно, адаптация аналитиков к «языку дизайна» может существенно упростить процесс


  1. ssurrokk
    18.11.2024 20:27

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