Sparround

Modullara bölmə: package-lər və melos

Qovluq bölgüsü qaydayı tövsiyə kimi saxlayır; paket bölgüsü onu məcburi edir. Fərq bir cümlədə: packages/domain paketinin pubspec.yaml-ında Flutter asılılığı yoxdursa, import 'package:flutter/material.dart' sətri kompilyasiya olunmur.

Bu, ən güclü qat qorunmasıdır, lakin qiyməti var:

  • Hər paketdə ayrı pubspec.yaml və versiya idarəsi.
  • Kod generasiyası (build_runner) hər paketdə ayrıca işlədilir.
  • Bir neçə paketdən sonra əmrləri hər paketdə işlətmək üçün alət lazımdır — bu, melos-un rolu.
  • Yeni komanda üzvü üçün başlanğıc mürəkkəbliyi artır.

Nə vaxt bölmək. Üç konkret siqnal:

1. Kod paylaşılır: mobil tətbiq + admin paneli, ya da mobil + server tərəfi Dart. Domain modelləri və validasiya qaydaları hər iki tərəfdə eyni olmalıdır. 2. Bir neçə komanda: hər komanda öz feature paketini müstəqil inkişaf etdirir və review sərhədləri aydın olur. 3. Build vaxtı: kod generasiyası bütün layihədə işlədikdə dəqiqələr çəkir; paketlərə bölündükdə yalnız dəyişən paket yenidən generasiya olunur.

Bu siqnallardan heç biri yoxdursa, qovluq bölgüsü + CI-də grep yoxlaması tam kifayətdir.

yaml
# ══ Struktur ══
# my_app/
# ├── pubspec.yaml                  ← workspace + melos konfiqurasiyası
# ├── packages/
# │   ├── domain/                   ← təmiz Dart: modellər, müqavilələr
# │   ├── data/                     ← service, DTO, repository impl.
# │   ├── ui_kit/                   ← paylaşılan widget-lər, tema
# │   ├── feature_orders/
# │   └── feature_loyalty/
# └── app/                          ← giriş nöqtəsi, DI, routing

# ══ my_app/pubspec.yaml (root) ══
name: my_app_workspace
publish_to: none

environment:
  sdk: ^3.6.0            # Pub workspace dəstəyi üçün minimum

# Pub workspace: paketlər bir `pub get` ilə həll olunur.
workspace:
  - packages/domain
  - packages/data
  - packages/ui_kit
  - packages/feature_orders
  - packages/feature_loyalty
  - app

# melos konfiqurasiyası — melos 7+ üçün eyni faylda.
dev_dependencies:
  melos: ^8.0.0

melos:
  scripts:
    analyze:
      run: dart analyze .
      exec:
        concurrency: 4
    test:
      run: flutter test
      exec:
        concurrency: 4
      packageFilters:
        dirExists: test        # yalnız testi olan paketlərdə
    generate:
      run: dart run build_runner build --delete-conflicting-outputs
      exec:
        concurrency: 2
      packageFilters:
        dependsOn: build_runner
    check-layers:
      run: ../../tool/check_layers.sh
      packageFilters:
        scope: domain

# ══ packages/domain/pubspec.yaml ══
# name: domain
# resolution: workspace
# environment:
#   sdk: ^3.6.0            ← `flutter:` bölməsi YOXDUR
# dependencies:
#   freezed_annotation: ^3.0.0     (təmiz Dart)
#   meta: ^1.15.0
# dev_dependencies:
#   build_runner: ^2.4.0
#   freezed: ^3.0.0
#   test: ^1.25.0                  (flutter_test DEYİL)

# ══ Əmrlər ══
# melos bootstrap        → bütün paketlərin asılılıqlarını həll edir
# melos run analyze      → hər paketdə `dart analyze`
# melos run test         → yalnız testi olan paketlərdə `flutter test`
# melos run generate     → yalnız build_runner-a ehtiyacı olanlarda
# melos exec -- <əmr>    → ixtiyari əmri hər paketdə işlədir

Monorepo quruluşu: root `pubspec.yaml` Pub workspace-i və melos konfiqurasiyasını daşıyır (melos 7+ ayrı `melos.yaml` işlətmir).

PaketFlutter asılılığıKimi import edə bilərMəqsədi
`domain`❌ YoxdurHeç kimi (yalnız təmiz Dart paketləri)Modellər, müqavilələr, `Failure`-lar, use-case-lər
`data`⚠️ Ola bilər (plugin-lər üçün)`domain`Service-lər, DTO-lar, repository implementasiyaları
`ui_kit`✅ VarHeç bir feature-i (yalnız Flutter)Tema, paylaşılan widget-lər, formatlaşdırıcılar
`feature_*`✅ Var`domain`, `ui_kit` — digər feature-i YOXBir feature-in notifier-ləri və ekranları
`app`✅ VarHamısınıGiriş nöqtəsi, DI qrafı, routing, flavor-lar

Paket qrafının qaydası. Ən vacib qərar: feature paketləri bir-birini import etmir. Əks halda paket bölgüsü faydasını itirir — feature_ordersfeature_catalogfeature_orders zənciri yaranır və heç bir paket müstəqil build olunmur.

Feature-lər arasında əlaqə iki yolla qurulur:

  • Paylaşılan məlumatdomain + data paketləri vasitəsilə. feature_ordersfeature_catalog hər ikisi ProductRepository-ni işlədir.
  • Naviqasiyaapp paketində. Feature yalnız "bu id ilə məhsul ekranına keç" niyyətini bildirir; marşrutları app bilir.

Bölgü strategiyası: tədricən. Bütün layihəni bir dəfəyə paketlərə bölmək lazım deyil. Adətən ən faydalı ardıcıllıq:

1. `domain` — ən çox qazanc verən addım: qat qaydası kompilyator səviyyəsində qorunur və testlər dart test ilə işləyir. 2. `ui_kit` — tema və paylaşılan widget-lər; ikinci tətbiq (tablet, admin) gələndə dərhal işə yarayır. 3. `data` — service-lər və repository implementasiyaları. 4. *`feature_`** — yalnız komanda sərhədləri yarandıqda.

Kod generasiyası barədə praktik qeyd. Paketlərə bölündükdən sonra build_runner hər paketdə ayrıca işlədilir. melos run generate bunu bir əmrlə edir, packageFilters: dependsOn: build_runner isə yalnız ehtiyacı olan paketləri seçir. Build vaxtı qazancı da buradan gəlir: yalnız dəyişən paket yenidən generasiya olunur.

Melos-un versiya nüansı. melos 7-ci versiyadan etibarən ayrı melos.yaml faylını işlətmir: konfiqurasiya root pubspec.yaml-ında melos açarı altında yaşayır, paketlərin yeri isə workspace açarında göstərilir (Pub workspace mexanizmi, Dart SDK 3.6.0+ tələb edir). İnternetdə tapdığın köhnə nümunələr melos.yaml göstərirsə, onlar 6.x və əvvəlki versiyalar üçündür.

Praktika (opsional — yalnız siqnallar varsa). Layihəndən domain qatını ayrı pakete çıxar:

1. packages/domain/ qovluğu yarat, pubspec.yaml-ında `flutter:` bölməsi olmadan. 2. lib/domain/* fayllarını oraya köçür (git mv). 3. Əsas pubspec.yaml-a domain: {path: packages/domain} əlavə et və import-ları düzəlt. 4. cd packages/domain && dart test işlət — Flutter olmadan işləməlidir.

Hazır sayılır: packages/domain/lib altında package:flutter import-u yazmağa cəhd etdikdə analizator xəta verir (bunu bir dəfə sınayıb geri qaytar), və domain testləri dart test ilə işləyir.

📚 Mənbələr və sənədlər

  • melos paketirəsmipub.dev

    `bootstrap`, `run`, `exec`, `version`, `publish` əmrləri və 7+ versiyada `pubspec.yaml`-daki konfiqurasiya.

  • Dart: paketlər yaratmaqrəsmidart.dev

    Paketin strukturu, `pubspec.yaml` və `lib/src/` konvensiyası.

  • Dart: Pub workspaces (monorepo)rəsmidart.dev

    `workspace` və `resolution: workspace` açarları — melos 7+ bunun üzərində işləyir.

  • Case study: strukturun icmalırəsmidocs.flutter.dev

    Müqayisə üçün: rəsmi nümunə tək paketdir və qovluq bölgüsü ilə kifayətlənir.