«Мобильное приложение должно работать без интернета» — в техническом задании это одна строка, а в плане работ она может занять половину проекта или не занять почти ничего. Разница в том, что вы имеете в виду под словом «работать».
Проверяется это одним вопросом: представьте пользователя в метро между станциями. Что он должен увидеть — последние загруженные данные, возможность что-то изменить или полноценную работу, как будто связь и не пропадала? Это три разных продукта и три разных срока, и только у третьего есть проблема, ради которой написана эта статья: что делать, когда один человек изменил запись офлайн, а второй в это же время изменил её же на сервере.
Приложение, в котором офлайн не продуман, ведёт себя в тоннеле узнаваемо. Экран пустеет или показывает бесконечный индикатор. Человек нажимает «обновить» — ничего. Нажимает «сохранить» — приложение молчит и выдаёт ошибку сети. Дальше начинается главное: он не знает, сохранилось что-нибудь или нет. И делает то же действие ещё раз.
Это источник большинства жалоб, которые приходят к вам как «приложение глючит». Не отсутствие функции, а неизвестность.
Поэтому разговор начинается не с технологий, а с двух кадров: что человек видит, когда связи нет, и что он видит через минуту после того, как она вернулась. Если на оба вопроса есть ответ в словах, а не в терминах, задачу можно оценивать. Если нет — оценка будет гаданием и у разных подрядчиков разойдётся в разы.
Первое: читать то, что уже загружено. Приложение помнит последние открытые экраны и показывает их без связи — расписание, документ, карточку товара. Рядом стоит отметка, когда данные получены, и честно сказано, что менять их нельзя. Такой уровень закрывает большинство бытовых ситуаций: посмотреть в самолёте, открыть в подвале, свериться в лифте. По нашей практике это самая выгодная часть работы — заметная человеку и самая дешёвая по трудозатратам из трёх.
Второе: отложить действие. Человек без связи ставит отметку о выполнении, пишет комментарий, сохраняет черновик — действие встаёт в очередь и уходит, когда появится сеть, и на экране видно, что оно ждёт отправки. Первая настоящая сложность появляется уже здесь, и она не в отправке. Человек нажал «отправить», связь моргнула, он нажал ещё раз. Если приложение не отличает повтор от нового действия, на сервере окажутся две заявки или два списания. Защита от этого — отдельная работа, и назвать её в составе работ стоит прямо.
Третье: полноценно работать без связи сколько угодно долго. Данные меняются на устройстве, а при подключении сводятся с тем, что за это время произошло на сервере. Это нужно выездным сценариям: осмотр объекта, приёмка на складе, работа на площадке, где сети нет полдня. Здесь начинаются конфликты версий, и здесь офлайн превращается в отдельный проект внутри проекта — со своей логикой, своими экранами и своим тестированием.
Практический вывод для разговора с подрядчиком. Попросите назвать, какой из трёх уровней заложен и по каким именно экранам. Ответ «приложение будет работать офлайн» без перечня экранов означает, что объём не считали.
Международная академия дополнительного профессионального образования EDPRO входит в топ-3 компаний сегмента дополнительного образования в России; через неё прошли более 10 000 учеников, а общая аудитория продуктов превышает 150 000 человек. Платформа уже работала в вебе, и задача была не «упаковать сайт в приложение».
В кейсе требование сформулировано дословно: создать лёгкое, быстрое и надёжное решение, способное работать даже при нестабильном интернете. Причина — аудитория. Это взрослые специалисты, в том числе проходящие переквалификацию, которым важно учиться в дороге или между рабочими сменами. Дорога и смена — как раз те места, где связь пропадает.
Что из этого вышло в продукте. Встроенная библиотека позволяет находить и просматривать учебные материалы, а при необходимости загружать их на устройство. Расписание автоматически синхронизируется с системой академии: перенос лекции или новый материал отражаются в приложении. Разные типы данных живут по разным правилам: материал человек забирает с собой сознательно, расписание приходит само и обязано быть свежим. Это и есть ответ на вопрос «что хранить»: не всё подряд и не по одному правилу.

Правило формулируется от обратного: на устройство попадает то, без чего конкретный офлайновый сценарий не состоится, и ничего сверх. Не «весь каталог на всякий случай», а список объектов, который можно назвать вслух.
Хорошо ложатся вещи, которые меняются редко и принадлежат одному человеку: справочники — перечень услуг, список статусов, формы документов; материалы, которые человек сам пометил «взять с собой»; его собственные черновики и незаконченные действия.
Плохо ложится то, что меняется у вас чаще, чем человек открывает приложение, и то, что меняют несколько людей сразу: остатки на складе, свободные слоты, состояние заказа, баланс. Показать их офлайн можно, но рядом обязана стоять дата и оговорка, что это снимок. Ровно поэтому в проектах с крупным каталогом обмен с учётной системой делают регулярным: в кейсе SHI TRENDY обмен каталогом и товарными остатками происходит полностью в автоматическом режиме. Объём тоже планируется заранее: кэш ограничивают по размеру и сроку хранения, иначе через полгода приложение удаляют первым при нехватке места.
Обстоятельство, про которое забывают: телефоны теряют, передают детям, отдают в ремонт, а увольняющийся сотрудник уносит свой с собой. Любая копия ваших данных на устройстве живёт по этим правилам, а не по правилам вашего офиса.
Отсюда минимум, который стоит потребовать от подрядчика. Чувствительные данные — сведения о клиентах, финансовые показатели, документы — либо не кладутся на устройство вовсе, либо хранятся в зашифрованном виде и привязаны к сеансу: при выходе или истечении срока локальная копия перестаёт открываться. Вход закрывается биометрией или кодом, а не паролем, введённым однажды год назад. В приложении «Центра сопровождения бизнеса», где человек видит остатки по счетам, текущие и запланированные платежи, поддержка Face ID и других биометрических методов и хранение данных в зашифрованном виде описаны в кейсе как часть решения.
Отдельно проговорите, что происходит при увольнении. Сервер отключается за минуту, а копию на чужом телефоне можно погасить, только если приложение изначально это умеет. Спросите прямо: что произойдёт с данными на устройстве человека, которого вы отключили в админке, и через какое время. Ответ «мы заблокируем учётную запись» на этот вопрос не отвечает.
Какие данные считать чувствительными и какие сроки хранения допустимы — решает ваша служба безопасности или ваш юрист, это не вопрос к разработчику. Задача разработчика другая: показать, что технически выполнимо и во что это обойдётся по срокам.
Самая дорогая ошибка в офлайне — не потерянные данные, а показанные уверенно и неправильно. Остаток, загруженный вчера, выглядит точно так же, как загруженный минуту назад. Человек принимает по нему решение, обещает клиенту, отгружает. Данные не врали — врал экран, который не сказал, что им сутки.
Поэтому каждому типу данных назначается срок, после которого приложение помечает их как устаревшие или перестаёт показывать вовсе. Для справочника услуг это недели, для расписания — часы, для остатка — минуты. Назначает сроки не разработчик: он не знает, с какой скоростью меняется ваш склад. Принять это решение стоит до проектирования экранов — отметка актуальности занимает место в макете.
Проверочный вопрос по каждому экрану: если цифры окажутся вчерашними, что сделает человек и чем это кончится? «Ничего страшного» — показывайте спокойно. «Подтвердит клиенту то, чего нет» — такие данные офлайн показывать нельзя, честнее сообщить, что без связи они недоступны.
Теперь собственно конфликт. Человек изменил запись на устройстве, пока был без связи. За это время её же изменил кто-то другой — коллега в офисе, учётная система, сам клиент в своём кабинете. Связь вернулась, две версии встретились. Кто-то должен выиграть, и это решение принимаете вы, а не технология.
Простейшее правило называется «последний победил»: выигрывает изменение с более поздней отметкой времени. Оно соблазнительно тем, что ничего не требует — ни экранов, ни обсуждений, ни лишних дней в плане. Для личных заметок, персональных настроек и черновиков, которые ведёт один человек, оно совершенно нормально.
Для заказов, записей и документов правило плохое, и причина не техническая: «последний победил» означает, что чья-то работа исчезает молча. Менеджер в офисе поменял адрес доставки по звонку клиента; выездной сотрудник без связи поменял в той же карточке комментарий; чья отметка времени оказалась позже, тот и записал карточку целиком — вместе с полями, которых не трогал. Адрес вернулся к старому значению, и сообщения об этом не было.
Вторая беда того же правила — часы на устройстве. Отметка времени берётся с телефона, а телефон может отставать, спешить или быть переведён вручную, и запись, сделанная раньше, легко оказывается «более поздней». Это штатная причина странных расхождений, и проверять её при приёмке надо отдельным сценарием: перевести время на телефоне и посмотреть, не выигрывает ли спор запись только из-за сбитых часов.
Рабочих альтернатив две, и обе объясняются без техники. Первая — сводить не запись целиком, а поля по отдельности: один поменял телефон, другой адрес — сохраняются оба изменения, а спор возникает, только если правили одно поле. Дороже по трудозатратам, зато убирает большую часть тихих потерь и хорошо подходит карточкам, которые ведут несколько человек.
Вторая — спросить человека: приложение показывает обе версии и предлагает выбрать. Единственный честный вариант там, где цена ошибки высокая, — деньги, количество, статус отгрузки, юридические записи. Он требует отдельно нарисованных экранов. И при любой стратегии нужен журнал: какая версия пришла, какая выиграла, кто и когда разрешил спор. Без журнала разбор задним числом невозможен — по общей практике это первое, чего не хватает, когда разбираться приходится.
Эта часть почти всегда пропускается в обсуждении и всплывает после запуска. Возвращение связи — отдельный сценарий со своими экранами, и проговорить его словами стоит до начала работ.
Минимум, который человек должен видеть: что приложение работает без связи; сколько его действий ждёт отправки; когда данные обновлялись; отдельное сообщение, когда всё ушло. Если что-то не ушло — что именно и что делать. Если возник спор версий — объяснение без слова «конфликт», которое человеку ничего не говорит.
Бывает и обратная крайность: приложение сообщает о каждой мелочи, и человек перестаёт читать сообщения вообще. Разумная середина — тихо показывать состояние и шуметь только там, где нужно его решение, а границу определять на макетах, а не в коде.
Офлайн почти никогда не ломается в честном режиме «полёта». Ломается он в плохой связи: запрос ушёл, ответ не пришёл, человек не дождался и нажал ещё раз. Поэтому проверка авиарежимом ничего не доказывает. Ниже — то, что стоит прогнать при приёмке и посмотреть своими глазами. Экономить на этом не стоит ещё и потому, что исправление доезжает до людей не сразу: публикация обновления в магазинах занимает дни, а дальше его должны установить — часть аудитории живёт со старой версией неделями.
Мы регулярно отговариваем от полноценного офлайна. Признаки, по которым решение стоит пересмотреть у себя, такие.
Ваши люди работают там, где связь есть: офис, торговый зал, квартира, город. Метро и самолёт занимают считаные минуты в день и закрываются первым уровнем. Второй признак: данные меняются у нескольких людей сразу и быстро — тогда офлайн не помогает работать, а производит споры версий, которые кто-то потом разбирает руками. Третий: цена ошибки высокая, а пользователь не готов разбирать расхождения. Человеку, который привёз заказ, экран «у нас две версии, выберите нужную» не поможет — он выберет наугад.
Чего офлайн стоит на самом деле: это не строка в смете, а сквозная тема. Он добавляет работу в проектирование — экраны состояния, отметки актуальности, экран разрешения спора. В разработку — очередь действий, защиту от повторов, сведение версий. В тестирование — все сценарии выше, каждый на двух устройствах. И навсегда в поддержку: каждое новое поле карточки с этого момента живёт в двух местах.
Разумный порядок поэтому такой. Сначала первый уровень — чтение загруженного с честной отметкой времени; он закрывает большинство жалоб и не меняет план проекта. Дальше смотрим, какие сценарии остались неудобными, и достраиваем отложенные действия для одного-двух конкретных экранов. Полноценная офлайн-работа со сведением версий включается тогда, когда у вас есть выездные люди без связи на часы, — и только для тех объектов, которые они действительно правят в поле.
Если вы сейчас решаете, нужен ли офлайн вашему приложению, опишите нам один рабочий день вашего пользователя: где он находится, что делает, когда у него пропадает связь и какие записи он при этом правит. Не техническое задание, а рассказ в несколько абзацев. Мы ответим, какой из трёх уровней закрывает этот день, какие объекты имеет смысл держать на устройстве, а какие опасно, и где у вас возникнут споры версий.
Если оценка от подрядчика уже есть — пришлите заодно и её, без названия студии. Скажем, стоит ли офлайн отдельной строкой или растворён в общей разработке. Второе означает ровно одно: до него дойдут в последнюю очередь.
Посмотрим ваш сайт, скажем, что мешает ему приводить клиентов, и какие каналы дадут результат в вашей практике. Без обязательств, отвечаем в течение рабочего дня.