Sparround

Qovluq strukturu: feature-first, layer-first və hibrid

Qovluq strukturu arxitektura deyil, lakin arxitekturanın görünən hissəsidir — komanda ona hər gün baxır. Üç variant var.

Layer-first — yuxarı səviyyədə qatlar: lib/domain, lib/data, lib/presentation. Hər qatın içində feature-lər.

  • Yaxşı: kiçik və orta layihədə çox sadə; qat qaydası göz qabağındadır.
  • Pis: bir feature-i dəyişəndə üç ayrı qovluqda gəzmək lazımdır; 30 ekranlıq layihədə presentation qovluğu nəhəng olur.

Feature-first — yuxarı səviyyədə feature-lər: lib/features/orders/{domain,data,presentation}. Hər feature öz qatlarını daşıyır.

  • Yaxşı: bir feature üzərində işləmək üçün bir qovluq kifayətdir; feature-i silmək və ya paketə çıxarmaq asandır.
  • Pis: paylaşılan kod problemə çevrilir. AuthRepository hansı feature-in içindədir? Cavab tapılmayanda core/ qovluğu "hər şeyin atıldığı yer" olur.

Hibrid — rəsmi Flutter bələdçisinin seçimi: UI feature-lərə görə, data qat üzrə bölünür. Səbəb sadə və inandırıcıdır: view və view model bir feature-ə aiddir, repository və service isə aid deyil — onlardan bir neçə feature istifadə edir.

text
lib/
├── ui/                        ← UI qatı: FEATURE-lərə görə
│   ├── core/
│   │   ├── ui/                ← paylaşılan widget-lər
│   │   └── themes/
│   └── <feature_adı>/
│       ├── view_models/
│       └── widgets/
├── domain/                    ← modellər (entity)
│   └── models/
├── data/                      ← data qatı: QAT üzrə
│   ├── repositories/
│   ├── services/
│   └── model/                 ← API modelləri (DTO)
├── config/
├── routing/
├── utils/
├── main.dart
├── main_development.dart      ← flavor-lar ayrı giriş nöqtələri
└── main_staging.dart

Diqqət: `/widgets` adlı qovluq yoxdur — paylaşılan widget-lər `ui/core/ui`
altındadır. Rəsmi tövsiyə budur: qovluq adı da qatı desin.

Rəsmi case study (Compass) tətbiqinin strukturu — hibrid yanaşmanın real nümunəsi.

MeyarLayer-firstFeature-firstHibrid (rəsmi)
Bir feature üzərində iş3 qovluqda gəzmək1 qovluqUI üçün 1 qovluq, data ortaq
Paylaşılan repositoryTəbii — `data/` ortaqdırProblemli — `core/` şişirTəbii — data qat üzrə bölünür
30+ ekranda naviqasiyaAğır: nəhəng `presentation/`RahatRahat
Feature-i pakete çıxarmaqÇətinAsanOrta — UI asan, data ortaq qalır
Merge konflikti riskiYüksək: hamı eyni qovluqlardaAşağıAşağı-orta
Nə vaxt seçmək< 10 ekran, tək developerBöyük, modullara bölünəcək layihəƏksər layihələr üçün standart

Qovluqlardan başqa iki qayda strukturu oxunaqlı saxlayır.

1. Ad sinfin qatını desin. Rəsmi tövsiyə: sinif adı onun arxitektur rolunu göstərsin — HomeViewModel, UserRepository, ProductApiClient. Flutter SDK-nın tiplərinə oxşayan adlardan çəkinmək lazımdır (Router, Route, State kimi). "Universal" şəkilçilərdən — Manager, Helper, Util — qaçmaq lazımdır: onlar qatı gizlədir və hər şeyin atıldığı sinifə çevrilir.

2. `test/` qovluğu `lib/`-i güzgü kimi təkrarlasın. lib/data/repositories/order_repository_remote.darttest/data/repositories/order_repository_remote_test.dart. Belə olduqda "bu sinfin testi var?" sualına cavab bir baxışla verilir.

Barrel fayllar (orders.dart içində export-lar) haqqında qısa qeyd: kiçik layihədə import-ları qısaldır, lakin qatlar arasında barrel yaratmaq asılılıq qaydasını gizlədir — import 'package:app/domain.dart' yazan adam nəyi gətirdiyini görmür. Qat sərhədlərində barrel-dən çəkinmək daha təhlükəsizdir.

Praktika. Layihən üçün qovluq strukturunu bir ARCHITECTURE.md faylında yaz: ağac diaqramı + hər qovluğun bir sətirlik təsviri + "nə buraya qoyulmur" qeydi. Sonra mövcud fayllarından 5-ni bu ağaca yerləşdir.

Hazır sayılır: fayl repoda var, ağacda domain, data və UI hissəsi aydın görünür, və ən azı bir qovluq üçün "buraya X qoyulmur, çünki ..." sətri yazılıb. Bu fayl sonra code review-da ən çox istifadə edəcəyin sənəd olur.

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