История изменений в мобильном приложении: реализация и оптимизация

Реализация истории изменений (Version History) в мобильном приложении Представьте: юрист правит договор на планшете, случайно удаляет абзац и сохраняет. Через час — подписание, а данных нет. Без истории изменений — катастрофа. Мы реализовали систему, которая хранит каждую правку и позволяет откат

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
История изменений в мобильном приложении: реализация и оптимизация
Средний
~5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Реализация истории изменений (Version History) в мобильном приложении

Представьте: юрист правит договор на планшете, случайно удаляет абзац и сохраняет. Через час — подписание, а данных нет. Без истории изменений — катастрофа. Мы реализовали систему, которая хранит каждую правку и позволяет откатить любую версию за секунды. В проектах с юридически значимыми документами, редакторской работой или сложными таблицами каждая правка должна быть отслежена и доступна для отката. Как спроектировать хранилище истории, чтобы оно не раздувалось и работало на мобильном устройстве с ограниченными ресурсами? Разбираем ключевые подходы, их сильные и слабые стороны, а также даём готовые схемы и код. Наш опыт — более 7 лет в мобильной разработке, мы реализовали версионирование в десятках проектов.

Два подхода: snapshot vs event sourcing

Snapshot — при каждом сохранении создаём полную копию объекта. Простота реализации и восстановления оборачивается взрывным ростом базы. Если документ весит 50 КБ, а пользователь сохраняет его 50 раз в день, за год накопится 50 × 50 × 365 ≈ 912 МБ только для одного документа. Для приложения с тысячами пользователей это неприемлемо.

Delta (event sourcing) — храним только разницу между версиями. Это компактно, но восстановление требует воспроизведения всех дельт от начального состояния. Для текста можно использовать diff-match-patch (бесплатная библиотека, доступна на iOS и Android). Однако сложность возрастает при параллельном редактировании.

Гибридный подход — комбинация: снэпшоты через каждые 10 версий или каждые 7 дней, между ними дельты. Восстановление: берём ближайший снэпшот и применяем дельты. Такой метод даёт до 90% экономии места по сравнению с чистыми снэпшотами и ускоряет восстановление в 5–10 раз относительно чистых дельт.

Ниже — сравнение трёх подходов.

Характеристика Snapshot Delta Гибрид
Объём хранилища Огромный Минимальный Средний
Скорость восстановления Мгновенно Медленно Быстро
Сложность реализации Низкая Высокая Средняя
Устойчивость к конфликтам Высокая Низкая Средняя

Схема данных

Для SQLite-базы на Android или CoreData на iOS мы используем такую таблицу:

@Entity(tableName = "document_versions") data class DocumentVersion( @PrimaryKey(autoGenerate = true) val id: Long = 0, val documentId: String, val versionNumber: Int, val deltaJson: String?, // null если snapshot val snapshotJson: String?, // null если delta val authorId: String, val deviceId: String, val createdAt: Long = System.currentTimeMillis(), val comment: String? = null // "Автосохранение" / "Сохранено вручную" ) 

Индекс по (documentId, versionNumber) обязателен — иначе выборка истории станет тормозом. На Android используем @Index в Room, на iOS — составной индекс в CoreData.

Как выбрать стратегию хранения версий?

Выбор зависит от типа данных и частоты изменений. Для документов с редкими правками (1–2 раза в день) чистый snapshot — просто и надёжно. Для текстовых редакторов, где правки происходят каждые секунды, лучше гибрид. Всегда оценивайте нагрузку: если база растёт быстрее, чем пользователи создают контент, меняйте подход.

Ограничение глубины истории

Хранить все версии вечно — нецелесообразно. Предлагаем три стратегии:

Стратегия Описание Пример лимита
Фиксированное количество Хранить последние N версий 50 версий
Временное окно Версии не старше M дней 30 дней
Умное прореживание Смешанный подход Полные за сутки, одна в день за неделю

Пример удаления старых версий на Android с WorkManager:

@Transaction suspend fun pruneVersions(documentId: String, keepCount: Int) { val versions = getVersionsByDocument(documentId) if (versions.size > keepCount) { val toDelete = versions.drop(keepCount) deleteVersions(toDelete.map { it.id }) } } 

Почему стоит ограничивать глубину истории?

Без ограничений база данных может раздуться до гигабайтов на устройстве. Пользователь редко возвращается к версиям старше месяца. Наш опыт показывает, что разумный лимит — 50 версий или 30 дней — покрывает 99% потребностей, а хранилище остаётся под контролем. Экономия на хранении — до 90% объёма БД, что напрямую снижает затраты на инфраструктуру.

UI истории версий

Список версий с датой, автором и типом (автосохранение/ручное). Тап — предпросмотр, две кнопки: «Восстановить» и «Сравнить с текущей». Diff-view с подсветкой: зелёный для добавленного, красный для удалённого. На мобильном используем inline diff через SpannableString (Android) или NSAttributedString (iOS) — компактно и интуитивно.

Автосохранение и дебаунс

Автосохранение не должно создавать версию на каждый символ. Дебаунс 2–3 секунды после последнего изменения:

private var saveTask: Task<Void, Never>? func textDidChange(_ text: String) { saveTask?.cancel() saveTask = Task { try? await Task.sleep(nanoseconds: 2_000_000_000) guard !Task.isCancelled else { return } await saveVersion(text, type: .auto) } } 

Что входит в работу

  1. Анализ данных и выбор стратегии (snapshot / delta / гибрид) — оцениваем нагрузку и гарантируем производительность.
  2. Проектирование схемы данных с индексами и внешними ключами.
  3. Реализация автосохранения с дебаунсом.
  4. Разработка UI списка версий с метаданными.
  5. Создание diff-view для сравнения версий.
  6. Настройка фоновой очистки устаревших версий по расписанию.
Пример полной реализации очистки с WorkManager (Android)
class VersionPruneWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { val dao = AppDatabase.getInstance(applicationContext).documentVersionDao() dao.pruneAllVersions(keepCount = 50) return Result.success() } } 

Сроки

Базовая реализация (snapshot + простой UI) — 1,5–2 дня. Полноценный гибрид с дельтами, diff-view и умным прореживанием — 4–5 дней. Стоимость рассчитывается индивидуально исходя из сложности данных и требований к глубине истории. Реализуем под ключ: от проектирования до публикации в сторах. Получите консультацию — напишите нам для оценки вашего проекта. Закажите внедрение истории изменений — мы предложим оптимальное решение.