BLoC-un təkamülü və qarışıq codebase
BLoC-un API-sı illər üzrə əhəmiyyətli dəyişikliklər keçib. Köhnə koda düşdükdə bunları tanımaq lazımdır — rəsmi migrasiya bələdçisindən:
bloc v8.0.0:
mapEventToStatesilindi, yerinəon<Event>API-sı gəldi.transformEventssilindi, yerinəEventTransformerAPI-sı.TransitionFunctiontypedef-i silindi.listensilindi, yerinəstream.listen.- Bağlanmış (closed) bloc-da
emitçağırmaq artıqStateErroratır və bu, tutulmamış exception kimionError-a çatdırılır. Sənədin izahı: əvvəl belə hallarda heç nə baş vermirdi və nəyin səhv getdiyini anlamaq çətin idi.
bloc v9.0.0:
- Bütün əvvəl deprecated edilmiş API-lar silindi;
BlocOverridesBloc.observervəBloc.transformerxeyrinə aradan qaldırıldı. - Yeni
EmittableStateStreamableSourceinterfeysi əlavə edildi:bloc_testəvvəlBlocBase-ə sıx bağlı idi, bu interfeysblocTest-i konkret implementasiyadan ayırmaq üçün gətirildi.
Ekosistemin digər paketləri öz versiya xəttini gedir: bloc_test 10.x, hydrated_bloc 11.x (orada HydratedCubit-in storage parametri adlı parametrə çevrildi).
// ❌ Köhnə API (bloc v8-də silindi): generator funksiya ilə state yayımı.
class CounterBlocOld extends Bloc<CounterEvent, int> {
CounterBlocOld() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
if (event is Increment) {
yield state + 1;
} else if (event is Decrement) {
yield state - 1;
}
}
}
// ✅ Aktual API: hər event tipi üçün ayrı handler.
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<Increment>((event, emit) => emit(state + 1));
on<Decrement>((event, emit) => emit(state - 1));
}
}
// Nə qazanılır:
// - `if (event is ...)` zənciri aradan qalxır, tip yoxlaması handler-in imzasındadır
// - hər handler-ə ayrı EventTransformer vermək mümkün olur (debounce, droppable)
// - handler-lər ayrı metodlara çıxarılıb test edilə bilərKöhnə API-nı tanımaq: `mapEventToState` → `on<Event>`.
Qarışıq codebase reallığı. Praktikada bir layihədə iki (bəzən üç) yanaşma yan-yana yaşayır: köhnə ekranlar Provider ilə, yeniləri BLoC və ya Riverpod ilə. Bu, texniki cəhətdən problem deyil — flutter_bloc özü package:provider üzərində qurulub — lakin idarə olunmalıdır.
İşləyən qaydalar:
- Sərhədi sənədləşdir: hansı hissə hansı yanaşma ilə yazılır. Yazılı qayda olmadan hər PR-da mübahisə yaranır.
- Feature daxilində qarışdırma: bir ekranda həm
BlocBuilder, həmConsumerolması ən pis haldır — oxunaqlılıq və debug çətinləşir. - Yeni kod bir yanaşma ilə: "boy scout rule" — toxunulan köhnə kod tədricən köçürülür.
- Ortaq layer-lər: repository/service qatı yanaşmadan asılı olmayan saxlanılır; bu, migrasiyanı ucuzlaşdıran əsas qərardır.
- Onboarding sənədi: yeni developer-ə hansı ekranda nə gözlədiyini izah edən qısa mətn.
| Vəziyyət | Tövsiyə |
|---|---|
| Köhnə ekran işləyir, dəyişiklik planlanmır | Toxunmamaq — işləyən kodu köçürmək dəyər gətirmir |
| Köhnə ekranda yeni feature əlavə olunur | Həmin ekranı köçürüb sonra əlavə etmək (əvvəlcə test yazmaqla) |
| Köhnə ekranda tez-tez bug çıxır | Köçürmə üçün ən yaxşı namizəd — investisiya özünü doğruldur |
| İki yanaşma bir ekranda | Texniki borc kimi qeyd edib ən qısa müddətdə birləşdirmək |
| Repository qatı yanaşmaya bağlıdır | Əvvəlcə bunu ayırmaq — migrasiyanın ən ucuz addımıdır |
Müsahibədə qarışıq codebase sualına ən güclü cavab "hər şeyi köçürərdim" deyil, prioritetləşdirmə meyarıdır: köçürmə dəyəri bug tezliyi, dəyişiklik tezliyi və komandanın həmin sahədə işləmə ehtimalı ilə ölçülür. Toxunulmayan, sabit işləyən ekranı köçürmək — heç bir dəyər gətirməyən risk götürməkdir.
📚 Mənbələr və sənədlər
- Bloc migrasiya bələdçisirəsmibloclibrary.dev
v8 və v9 breaking dəyişikliklərinin, mapEventToState-in silinməsinin rəsmi mənbəyi.
- Bloc konseptlərirəsmibloclibrary.dev
- package:blocrəsmipub.dev
Aktual versiya və changelog.
- package:hydrated_blocrəsmipub.dev