Перейти к основному содержанию
`Ctrl`+`K`

# Приложение A

## Ключевые усложнения нативного SDK

- Несогласованные фоновые операции
  REST-запрос стартовал в `IO`, запись в SQLite — в `Default`, обратное уведомление пришло в `mainThread`. Малейшая задержка вызывала гонку и слепой интерфейс.

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

- Boilerplate
  Room → Repository → UseCase → ViewModel → LiveData → Compose. Каждая сущность дублирует набор полей — правка трёх строк превращалась в десять правок и pull-request на 200 строк.

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

- Трудная интеграция железа
  Камера, NFC, голосовой ввод требовали кастомных сервисов, контекстных разрешений и многословного DI-кода.

### Детальное описание преодолённых усложнений

Усложнение | Решение, предоставляемое GlobalErp Mobile Framework
--- | ---
Последовательное выполнение долгих операций блокирует UI | Вся логика БД, сетевые вызовы и файловые операции выполняются в едином серверном потоке. Поток UI занят только отрисовкой.
Race condition между результатами запросов | Подписка осуществляется на `ObservableRecord`; события доставляются строго в порядке фиксации транзакции.
Разрозненные реализации retry-логики для REST, файлов и локальной БД | `Pkg`, `Api`, `FileManager` работают внутри той же транзакции GsSession. `commit` / `rollback` выполняются единообразно.
Сложность атомарного отката: часть данных уже записана, часть — нет | `GsSession` объединяет БД, файлы, сеть и любые пакеты, созданные пользователем: единая транзакция обеспечивает согласованный откат.
Отмена длительной операции оставляет систему в непредсказуемом состоянии | `InterruptingLock` прерывает SQL, REST и вычисления; стек состояний автоматически откатывается к стабильному экрану.
Навигация разбросана между `Activity`, флагами back stack и коллбэками | Стек-ориентированная навигация (`SmState` + `SmTrans`) управляется на серверном потоке. Решения о переходах принимаются до синхронизации с UI.
Передача данных между слоями требует множества Mapper / Repository / ViewModel | Цепочка SQL → RecordSet → Compose избавляет от промежуточных слоёв. Данные приходят в UI напрямую.
Хрупкий офлайн-режим, необходимость писать очередь синхронизации | Все изменения фиксируются локально; синхронизация с сервером оформляется единообразно через очереди задач и `Flow`, без разрозненных сервисов.
Сложная интеграция аппаратных функций (камера, NFC, QR-сканер) | Плагины `ActivityPlugin` подключаются в `GsBaseActivity`. Дополнительных DI-конфигураций не требуется.
Несогласованная обработка аппаратной кнопки «Назад» и жестов | `Navigator` централизованно управляет `TopBar`, `BottomBar`, FAB и back-навигацией для всех экранов.
Невозможность гарантировать порядок выполнения фоновых задач при навигации | Задачи (`postSharedTask`, `postAsyncTask`) регистрируются в очереди событий State Manager. Выполняются строго после завершения предыдущих транзакций.
Отсутствие единых правил для тестирования | `State` / `VCI` можно запускать с параметром `database = null`; достаточно