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

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

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

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

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

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

Реализация истории изменений (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 дней. Стоимость рассчитывается индивидуально исходя из сложности данных и требований к глубине истории. Реализуем под ключ: от проектирования до публикации в сторах. Получите консультацию — напишите нам для оценки вашего проекта. Закажите внедрение истории изменений — мы предложим оптимальное решение.

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

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

  • Разработка мобильного приложения для компании FEEDME
    Разработка мобильного приложения для компании FEEDME
    1010
  • Разработка мобильного приложения для компании XOOMER
    Разработка мобильного приложения для компании XOOMER
    903
  • Разработка мобильного приложения для компании RHL
    Разработка мобильного приложения для компании RHL
    1332
  • Разработка мобильного приложения для компании ZIPPY
    Разработка мобильного приложения для компании ZIPPY
    1180
  • Разработка мобильного приложения для компании Affhome
    Разработка мобильного приложения для компании Affhome
    1107
  • Разработка мобильного приложения для компании FLAVORS
    Разработка мобильного приложения для компании FLAVORS
    714