
Мобильный продукт живёт в мире прерываний
Сценарий нельзя считать непрерывным: приложение уходит в background, socket закрывается, сеть меняется с Wi‑Fi на LTE, push-разрешение отзывается, процесс может быть выгружен ОС. Архитектура должна считать reconnect нормальным переходом состояния, а не исключением.
Восстановление соединения — это новая синхронизация, а не продолжение старой сессии
После возврата клиенту нужен свежий snapshot и новая точка отсчёта. Устаревшие запросы отменяются, локальные optimistic updates сверяются с server authority, а повторять автоматически можно только идемпотентные команды. Денежное действие нельзя отправлять снова потому, что UI не дождался ответа.
Разрешение на уведомления следует после объяснения ценности
Сначала пользователь выбирает конкретную подписку — например, старт матча или изменение счёта. Только затем имеет смысл просить системное разрешение. Topic preferences, quiet hours и состояние OS permission — разные уровни и не должны смешиваться в одном флаге.
Телеметрия мобильного клиента — контракт, а не список кнопок
События версиионируются и несут общий context envelope: app version, screen, session, connectivity class и schema version. Персональные или чувствительные поля не должны попадать в telemetry «по привычке». Серверная валидация схемы позволяет видеть несовместимые клиенты после rollout.
Релиз учитывает долгоживущие соединения и старые версии клиента
Мобильный клиент невозможно обновить мгновенно у всех пользователей. Backend должен выдерживать совместимость с несколькими версиями приложения; stream protocol — иметь version fence; rollout — отслеживать reconnect loop, crash-free sessions и ошибки конкретной app version.
Матрица режимов работы вместо одного штатного сценария
Для mobile стоит тестировать не «экран», а переходы между runtime-состояниями. Один и тот же пользователь может начать действие online, уйти в background до ответа и вернуться уже на другой сети. Локальный draft допустимо восстановить; финальный результат команды нужно перечитать с сервера.
| Runtime | Что сохраняем | Что перепроверяем |
|---|---|---|
| Foreground / online | UI context и безопасный draft | Quote, permissions, live version |
| Background | Минимальный recoverable context | Возраст snapshot и активность socket |
| Offline | Только действия, которые честно могут ждать | Все server-authoritative решения |
| Reconnect | Intent пользователя | Новый snapshot, cursor и статус ранее отправленных команд |
Это же влияет на UX push-уведомлений: tap по notification должен вести не в устаревший cached screen, а в маршрут, который умеет получить текущий state и корректно объяснить, если событие уже завершилось.
Что команда должна уметь воспроизвести на тестовом устройстве
Mobile acceptance полезно строить вокруг переходов runtime, а не набора статичных screen shots. Тестовый сценарий должен включать background, смену сети, kill/relaunch, отзыв notification permission и возвращение по deep link из push.
- Начать critical flow и увести приложение в background до ответа сервера.
- Вернуться после истечения локального snapshot и проверить full resync.
- Сменить сеть во время stream connection и убедиться, что активна одна новая сессия.
- Открыть push после завершения события: маршрут должен загрузить terminal state, а не старый cached view.
Результат такого теста — не «не упало», а корректно объяснённое пользователю состояние и отсутствие дубликатов команд.
Проверка на устройстве важнее идеального сценария в симуляторе
Mobile-продукт стоит тестировать в неудобных условиях: начать действие на Wi‑Fi, уйти в background, переключиться на мобильную сеть, открыть push и вернуться в уже устаревший экран. Такой прогон показывает, действительно ли приложение умеет заново согласовать состояние, а не просто повторяет запросы.
Если после reconnect клиент может безопасно продолжить, значит границы выбраны удачно: MobileSyncCoordinator отвечает за новую точку синхронизации, экран читает актуальный snapshot, а команда с необратимым результатом не отправляется повторно без сверки сервера.
Где мобильный пользовательский опыт ломается не в макете, а в дороге
На презентации мобильный продукт почти всегда выглядит устойчивым. Настоящая проверка начинается в лифте, метро и во время быстрой смены сети, когда приложение то уходит в background, то возвращается с уже устаревшим snapshot. Поэтому полезно заранее описать, что именно восстанавливается локально, а что должно быть подтверждено заново через координатор мобильной синхронизации.
Отдельный класс ошибок связан не с transport, а с тем, как приложение объясняет состояние пользователю. Push пришёл, permission системно отключён, quiet hours активны, матч уже завершён — для каждого такого случая нужен свой текст и допустимое действие. Это хорошо видно в статье про push-подписки и quiet hours, где граница между продуктовой настройкой и системным разрешением разложена без абстракций.
Поддерживающие материалы
Ниже — подробные разборы отдельных решений: от состояния интерфейса и границ компонента до интеграции и поведения при отказе.