11 KiB
📦 Стоит ли выносить Database (Drift + DAO) в отдельный пакет?
🤔 Краткий ответ
Для текущего проекта: НЕТ, выносить не нужно.
Но давайте разберем, когда это имеет смысл, а когда нет.
✅ Когда выносить имеет смысл
1. Множественное использование в разных проектах
Если database используется в нескольких независимых проектах:
mnemo_cards_database/ ← Отдельный пакет
├── lib/
│ ├── database.dart
│ ├── tables/
│ └── daos/
└── pubspec.yaml
mnemo_cards_backend/ ← Использует database
└── pubspec.yaml
dependencies:
mnemo_cards_database:
path: ../mnemo_cards_database
mnemo_cards_admin_tool/ ← Тоже использует database
└── pubspec.yaml
dependencies:
mnemo_cards_database:
path: ../mnemo_cards_database
mnemo_cards_analytics/ ← И это тоже
└── pubspec.yaml
dependencies:
mnemo_cards_database:
path: ../mnemo_cards_database
Плюсы:
- ✅ Переиспользование в нескольких проектах
- ✅ Централизованное управление схемой БД
- ✅ Общие миграции для всех проектов
- ✅ Избежание дублирования кода
Когда это нужно:
- У вас несколько backend сервисов (микросервисы)
- Есть отдельные инструменты (admin panel, analytics, migration tools)
- Разные команды работают с одной БД
2. Публикация как библиотека
Если вы хотите опубликовать database layer как отдельную библиотеку:
# mnemo_cards_database/pubspec.yaml
name: mnemo_cards_database
version: 1.0.0
publish_to: pub.dev # Публикуется для всех
Плюсы:
- ✅ Можно использовать в других проектах
- ✅ Версионирование отдельно от backend
- ✅ Переиспользование в открытых проектах
3. Тестирование изолированно
Если нужно тестировать database layer отдельно:
mnemo_cards_database/
├── lib/
└── test/
└── database_test.dart # Тесты только для database
mnemo_cards_backend/
└── test/
└── integration_test.dart # Интеграционные тесты
Плюсы:
- ✅ Изолированное тестирование database layer
- ✅ Можно тестировать без запуска всего backend
Но: Обычно этого можно достичь и без вынесения в отдельный пакет.
❌ Когда выносить НЕ нужно (ваш случай)
1. Один проект использует database
Текущая ситуация:
mnemo_cards_backend/
├── lib/
│ ├── database/ ← Используется ТОЛЬКО здесь
│ │ ├── database.dart
│ │ ├── tables/
│ │ └── daos/
│ ├── api/ ← Использует database
│ ├── user/ ← Использует database
│ └── packs/ ← Использует database
└── pubspec.yaml
Почему не нужно выносить:
- ❌ Нет переиспользования (только один потребитель)
- ❌ Усложняет структуру проекта без выгоды
- ❌ Больше файлов для навигации
- ❌ Дополнительные настройки pubspec.yaml
- ❌ Усложняет рефакторинг (нужно менять два пакета)
2. Тесная связанность с бизнес-логикой
В вашем проекте database тесно связана с backend:
// database используется ВЕЗДЕ в backend
lib/api/v2/users_api_v2.dart → database
lib/user/user_manager.dart → database
lib/packs/pack_manager.dart → database
lib/api/purchase/payment_manager.dart → database
lib/cron/*.dart → database
Проблемы при выносе:
-
Циклические зависимости:
mnemo_cards_database/ └── нужно что-то из mnemo_cards_backend (конвертеры, хелперы) mnemo_cards_backend/ └── зависит от mnemo_cards_database -
Конвертеры и extensions:
// Где должны быть эти extensions? extension UserToUserModel on User { ... } // В database или backend? extension CardPackToCardPackModel on CardPack { ... } -
Зависимости:
// database.dart использует converters.dart // converters.dart может использовать что-то из backend
3. Database специфична для backend
В вашем проекте:
- Database структура создана специально для backend логики
- Таблицы отражают бизнес-логику backend
- DAO методы оптимизированы под нужды backend
- Нет планов использовать в других проектах
Если database специфична для одного проекта - выносить не стоит.
📊 Сравнение: Ваш проект vs Когда нужно выносить
| Критерий | Ваш проект | Когда нужно выносить |
|---|---|---|
| Количество потребителей | 1 (только backend) | 3+ проекта |
| Микросервисы | Нет | Да, несколько сервисов |
| Общая БД | Одна БД для backend | Одна БД для многих сервисов |
| Переиспользование | Нет | Да, используется в разных местах |
| Независимая разработка | Нет | Да, разные команды |
| Версионирование | Одно с backend | Отдельное версионирование |
🎯 Альтернативы вынесению
1. Модульная структура внутри проекта
Вместо отдельного пакета, используйте модульную структуру:
mnemo_cards_backend/
├── lib/
│ ├── database/ ← Database модуль (НЕ отдельный пакет)
│ │ ├── database.dart
│ │ ├── tables/
│ │ └── daos/
│ ├── api/ ← API модуль
│ ├── user/ ← User модуль
│ └── packs/ ← Packs модуль
Плюсы:
- ✅ Четкое разделение ответственности
- ✅ Легко навигироваться
- ✅ Нет проблем с зависимостями
- ✅ Можно вынести позже, если понадобится
2. Barrel exports для изоляции
Создайте единую точку входа для database:
// lib/database/database.dart
export 'database_impl.dart';
export 'daos/user_dao.dart';
export 'daos/pack_dao.dart';
// ...
// Использование:
import 'package:mnemo_cards_backend/database/database.dart';
Плюсы:
- ✅ Чистые импорты
- ✅ Легко рефакторить (меняем только один файл)
- ✅ Можно вынести позже (меняем только exports)
🔮 Когда стоит пересмотреть решение
Если появятся:
-
Второй backend сервис:
mnemo_cards_backend_api/ ← Основной API mnemo_cards_backend_admin/ ← Admin API→ Тогда имеет смысл вынести общую database
-
Отдельные инструменты:
mnemo_cards_migration_tool/ ← Миграции mnemo_cards_analytics/ ← Аналитика→ Тогда имеет смысл вынести database
-
Публикация как библиотека:
- Если планируется публикация на pub.dev → Тогда нужно вынести в отдельный пакет
💡 Рекомендации для вашего проекта
✅ Что делать СЕЙЧАС:
-
Оставить database внутри backend:
mnemo_cards_backend/ └── lib/ └── database/ ← Остается здесь -
Использовать модульную структуру:
- Четко разделять database, api, user, packs модули
- Использовать barrel exports для чистоты импортов
-
Документировать архитектуру:
- Описать модульную структуру
- Объяснить, когда и как выносить в отдельный пакет
❌ Что НЕ делать:
- ❌ Не выносить database в отдельный пакет без необходимости
- ❌ Не усложнять структуру без реальной выгоды
- ❌ Не создавать лишние абстракции
📝 Вывод
Для вашего проекта: НЕ ВЫНОСИТЬ
Причины:
- ✅ Database используется только в одном проекте (backend)
- ✅ Тесная связанность с бизнес-логикой backend
- ✅ Нет планов на переиспользование
- ✅ Вынос усложнит структуру без выгоды
Когда пересмотреть решение:
- 🔄 Появится второй сервис, использующий ту же БД
- 🔄 Появится отдельный инструмент (admin, analytics)
- 🔄 Планируется публикация database как библиотеки
- 🔄 Разные команды будут работать с database независимо
Альтернатива:
✅ Используйте модульную структуру внутри проекта:
- Четкое разделение модулей
- Barrel exports для изоляции
- Легко вынести позже, если понадобится
Итог: Ваша текущая структура правильная для проекта с одним backend. Выносить database в отдельный пакет стоит только когда появится реальная необходимость (несколько потребителей, переиспользование).