Проект построен на принципах Clean Architecture с разделением на слои и мультимодульной структурой.
Основные характеристики архитектуры:
| Характеристика | Значение |
|---|---|
| Min SDK | 26 (Android 8.0 Oreo) |
| Архитектурный паттерн ui | MVVM |
| UI Framework | Jetpack Compose |
| DI Framework | Kotlin-inject + Anvil |
| Навигация | Decompose |
| Локальная БД | SqlDelight |
Проект организован в виде набора модулей, каждый из которых отвечает за определённую функциональность:
epub/
├── app/ # Точка входа приложения, Android-конфигурация, Application class
│
├── core/ # Общие компоненты
│ ├── data/ # Общие data-компоненты
│ ├── domain/ # Общие доменные компоненты
│ ├── routing/ # Общая маршрутизация
│ ├── uikit/ # UI-кит
│ └── ui/ # Общие UI-компоненты
│
├── feature/ # Функциональные модули (фичи)
│ └── reader/ # EPUB-ридер
│
├── lib/ # Внутренние библиотеки
│ └── epub/ # EPUB-парсер
│
└── build-conventions/ # Сборочные скрипты
feature-модули состоят из 4 подмодулей по слоям:
| Подмодуль | Назначение | Содержит |
|---|---|---|
data |
Работа с данными | Реализация репозитория, API-вызовов (для будущего расширения функциональности), БД |
domain |
Бизнес-логика | Интерфейс репозитория, доменная модель |
ui |
Пользовательский интерфейс | Screen, ViewModel, компоненты |
routing |
Навигация | DI компонент, компонент навигации |
UI-слой отвечает за отображение данных и взаимодействие с пользователем.
Структура UI-модуля фичи:
feature/*/ui/
├── screen/
│ ├── FeatureScreen.kt # Основной экран
│ ├── ViewState.kt # Состояние UI
│ └── FeatureViewModel.kt # Логика экрана
└── component/ # Переиспользуемые компоненты
Доменный слой содержит бизнес-логику.
Структура Domain-модуля фичи:
feature/*/domain/
├── FeatureRepository.kt # Интерфейс репозитория
├── FeatureModel.kt # Доменная модель (логика и состояния пользовательского сценария)
└── entity/ # Сущности доменного слоя
Data-слой отвечает за получение данных из внешних источников.
Структура Data-модуля фичи:
feature/*/data/
└── FeatureaDataRepository.kt # Реализация репозитория
В проекте используется MVVM паттерн без внешних зависимостей.
Состояние экрана — immutable data class, содержащий все переменные для отображения UI.
События навигации, обрабатывающиеся в компоненте навигации.
Однократные события, используемые для рендеринга сообщений (снекбаров) и модальных окон
Навигация построена на фреймворке Decompose.
feature/*/routing/
├── ReaderNavigationComponent.kt # Логика переходов между экранами сценария (фичи)
├── FeatureFlow.kt # Вызовы функций экранов
└── FeatureFlowComponent.kt # DI-компонент
В стандартном сценарии для получения событий ошибок асинхронных задач (таких как открытие epub файла), используется подписка на состояние Task доменной модели. Подписка реализуется в коде ViewModel, и использует:
- ViewState для отображения состояний полноэкранной ошибки,
- ViewEvents для отображения ошибок пользователю в виде снекбаров или модальных окон
| Ограничение | Влияние | Митигация |
|---|---|---|
| отсутствует реализация защиты авторских прав (DRM) | Не поддерживается | Только открытые EPUB |
Работа с EPUB организована в несколько этапов:
- Выбор файла через пользовательский сценарий или открытие файла через ФС с выбором приложения
- Файл доступен приложению по content uri и для последующего доступа копируется в директорию приложения
- Читаются метаданные файла с помощью реализации парсера в модуле :lib:epub и записываются в локальную БД
- Файл открывается внутри пользовательского сценария и производится полный парсинг всех элементов файла
- Полученная структура данных используется для расчета числа страниц и рендерится Compose функциями
- Для сохранения позиции прогресса используется запись в локальную БД последнего видимого на экране элемента
| Инструмент | Назначение |
|---|---|
| Firebase Crashlytics | Сбор крашей в production |
P0 — Critical (влияет на основной флоу)
├── Падения при запуске
└── Потеря данных пользователя, ошибки миграции БД
P1 — High (влияет на ключевые функции)
├── Не открывается книга
└── Проблемы с загрузкой контента
P2 — Medium (влияет на UX)
├── Мелкие визуальные баги
├── Проблемы с производительностью
└── Не критичные ошибки
P3 — Low (улучшения)
├── Фичи не работают как ожидается
└── Косметические проблемы
- Обнаружение → Crashlytics/пользовательские отчёты
- Классификация → Определение приоритета по воздействию
- Эскалация → P0/P1 → немедленное уведомление команды
- Исследование → Анализ, воспроизведение
- Исправление → Hotfix или плановая поставка
- Верификация → Проверка в CI, ручное тестирование
- Релиз
| Тип | Источник | Обработка |
|---|---|---|
| Parse Errors | Serialization, IO errors | FileError |
| Database Errors | SqlDelight | IOException |
| Unexpected Errors | Uncaught exceptions | Crashlytics, fallback UI |
Источники данных для анализа:
├── Crashlytics Dashboard
│ ├── Non-fatals (handled exceptions)
│ ├── ANRs
│ └── Breadcrumbs
├── AppMetrica
│ ├── Crash logs
│ └── Events funnel
└── Firebase Analytics
└── Custom error events
- Локализация — Определение модуля и условий воспроизведения
- Приоритизация — Оценка impact и срочности
- Исправление — Минимальный change set
- Тестирование — Unit tests + Manual verification
- Релиз — Cherry-pick в release branch или плановая поставка
| Тип | Trigger | Назначение |
|---|---|---|
| dev-build | MR в develop | Тестирование разработчиками |
| internal-build | MR в main | Внутреннее тестирование |
| release-build | MR в release | Production |
main (production)
├── release/* (release branches)
└── develop (development)
└── feature/* (feature branches)
1. Feature development → MR в develop
2. Code review + CI checks (ktlint, detekt, tests)
3. Merge в develop → auto internal-build
4. Заморозка фич → создание release/* от develop
5. QA на release candidate
6. Git tag vX.Y.Z → release-build → production
7. Merge release/* обратно в develop и main
| Компонент | Версия | Notes |
|---|---|---|
| JDK | 17+ | Требуется для AGP 8.x |
| Android SDK | API 26+ | Min SDK проекта |
| Gradle | 8.x | Wrapper included |
| Kotlin | 2.3.20 | Определён в libs.versions.toml |
| AGP | 8.13.2 | Android Gradle Plugin |
Специальных шагов для сборки и запуска проекта не требуется, используется стандартный инструментарий Android Studio
# 1. Установить JDK 17+
# На macOS:
brew install openjdk@17
# На Ubuntu:
sudo apt install openjdk-17-jdk
# 2. Установить Android SDK
# Скачать с https://developer.android.com/studio
# Или через sdkmanager:
sdkmanager "platforms;android-34" "build-tools;34.0.0"Специальных шагов для сборки и запуска проекта не требуется, используется стандартный инструментарий Android Studio
# 1. Клонировать репозиторий
git clone <repository-url>
cd epub
# 2. Собрать debug APK
./gradlew assembleDebug
# 3. Установить на устройство/эмулятор
./gradlew installDebug| Библиотека | Версия | Назначение |
|---|---|---|
| Jetpack Compose | 1.10.6 | UI фреймворк |
| Compose Material3 | 1.4.0 | Material3 ui компоненты |
| Coil | 3.4.0 | Работа с изображениями |
| Библиотека | Версия | Назначение |
|---|---|---|
| Kotlin-inject | 0.8.0 | DI фреймворк |
| Decompose | 3.5.0 | Фреймворк навигации |
| SqlDelight | 2.3.2 | БД |
| Библиотека | Версия | Назначение |
|---|---|---|
| Jsoup | 1.18.3 | HTML парсер |
| Kotlinx DateTimme | 0.7.1 | Kotlin date/time |
| Timber | 5.0.1 | Библиотека логгирования |
| Firebase Crashlytics | 20.0.5 | Библиотека для логгировнаия сбоев |
| Инструмент | Версия | Назначение |
|---|---|---|
| Detekt | 1.23.8 | Static analysis |
| KtLint | 0.46.0 | Code formatting |
| Android Cache Fix | 3.0.3 | Gradle cache fixes |