Branch by Abstraction — katta kod o‘zgarishini uzoq muddatli source branch yaratmasdan, abstraction qatlam ortida bosqichma-bosqich amalga oshirish usuli. Eski va yangi implementation bir muddat bir codebase ichida mavjud bo‘ladi, traffic yoki chaqiriqlar asta-sekin yangi variantga o‘tkaziladi.
Pattern trunk-based development, katta refactoring va xavfsiz migrationlarda ishlatiladi.
Muammo
Database access qatlamini to‘liq almashtirish haftalar davom etishi mumkin.
Alohida long-lived branch yaratilsa:
- main branchdan uzoqlashadi;
- merge conflict ko‘payadi;
- integration kechikadi;
- release qilish qiyinlashadi;
- xato oxirida aniqlanadi.
Branch by Abstraction o‘zgarishni kichik commitlarda main branchga qo‘shadi.
Abstraction yaratish
Avval eski implementation oldiga interface yoki facade qo‘yiladi.
Masalan:
OrderRepository
Eski code shu abstraction orqali ishlaydigan holatga keltiriladi.
Bu bosqichda behavior o‘zgarmaydi.
Eski implementation
Mavjud code interface’ni amalga oshiradi:
LegacyOrderRepository
Application oldingidek ishlaydi.
Refactoring regression testlar bilan tekshiriladi.
Yangi implementation
Yangi variant shu interface ortida yoziladi:
NewOrderRepository
U yangi database, library yoki architecture’dan foydalanishi mumkin.
Eski va yangi implementation bir xil contract testdan o‘tadi.
Switch
Configuration yoki feature flag qaysi implementation ishlatilishini tanlaydi.
Masalan:
ORDER_REPOSITORY=legacy
ORDER_REPOSITORY=new
Switch environment, tenant, user yoki traffic foizi bo‘yicha bo‘lishi mumkin.
Incremental rollout
Yangi implementation avval:
ishlatiladi.
Metric va errorlar eski variant bilan taqqoslanadi.
Muammo bo‘lsa switch tezda ortga qaytariladi.
Dark launch
Yangi implementation natijasi production traffic bilan hisoblanadi, ammo clientga eski natija qaytariladi.
Ikki natija taqqoslanadi.
Bu read operation uchun qulay.
Write operationni ikki marta bajarish side effect yaratishi mumkin.
Dual read
Eski va yangi source’dan o‘qilib, natijalar solishtiriladi.
Farqlar log yoki metricga yoziladi.
Clientga bitta authoritative natija qaytariladi.
Data ordering, timestamp va defaultlar taqqoslashda normalizatsiya qilinadi.
Dual write
Bir operation eski va yangi storage’ga yoziladi.
Bu migrationni sinxron ushlashga yordam beradi.
Ammo bir write muvaffaqiyatli, ikkinchisi xato bo‘lishi mumkin.
Outbox, change capture yoki reconciliation kerak.
Feature flag
Feature flag abstraction switchini boshqaradi.
Flag:
ga ega bo‘ladi.
Migration tugagach flag va eski branch olib tashlanadi.
Contract test
Ikkala implementation bir xil behavior contractga mosligi tekshiriladi.
Masalan:
- create;
- read;
- update;
- not found;
- concurrency;
- transaction;
- error mapping.
Implementation-specific detal testga kiritilmaydi.
Database migration
Schema yoki storage almashtirilganda jarayon:
- abstraction;
- yangi schema;
- backfill;
- change synchronization;
- dual read;
- traffic switch;
- validation;
- eski storage cleanup.
Har bosqich deploy qilinadigan va rollback qilinadigan bo‘lishi kerak.
Library almashtirish
Eski third-party library to‘g‘ridan-to‘g‘ri ko‘p joyda ishlatilsa avval adapter interface yaratiladi.
Keyin barcha call site’lar adapterga o‘tkaziladi.
Yangi library adapteri qo‘shilib switch qilinadi.
Bu tashqi API farqlarini bir joyda saqlaydi.
UI migration
Eski va yangi UI component bir feature flag ostida ishlashi mumkin.
Routing yoki component factory qaysi variantni ko‘rsatishni tanlaydi.
Analytics va user feedback rolloutni baholaydi.
Trunk-based development
Barcha kichik qadamlar tez-tez main branchga merge qilinadi.
Incomplete yangi implementation default holatda o‘chiq bo‘ladi.
Main branch doim release qilinadigan holatda saqlanadi.
Abstraction leakage
Interface faqat eski implementation shaklini ko‘chirsa yangi model imkoniyatini cheklashi mumkin.
Abstraction business capability asosida tuziladi.
Legacy detail domain contractga kiritilmaydi.
Cleanup
Migration muvaffaqiyatli tugagach:
- eski implementation;
- eski config;
- feature flag;
- dual-write code;
- comparison metric;
- compatibility workaround
olib tashlanadi.
Aks holda vaqtinchalik abstraction doimiy murakkablikka aylanadi.
Rollback
Switchni ortga qaytarish faqat data compatibility saqlansa oson.
Yangi implementation eski tizim tushunmaydigan data yozgan bo‘lsa code rollback yetarli emas.
Forward va backward data compatibility rejalashtiriladi.
Observability
Eski va yangi variant bo‘yicha alohida kuzatiladi:
- latency;
- error;
- result difference;
- data count;
- throughput;
- resource;
- business metric.
Faqat texnik success emas, business natija ham solishtiriladi.
Kichik commitlar
Migration katta bo‘lsa ham har commit productionga deploy qilinadigan holatda bo‘ladi.
Masalan:
- interface qo‘shish;
- eski implementationni interface ortiga o‘tkazish;
- metric qo‘shish;
- yangi implementation skeleti;
- read-only shadow;
- kichik rollout.
Bu code review va rollbackni soddalashtiradi.
Data contract
Eski va yangi implementation bir xil object yoki database contractini ko‘rmasligi mumkin.
Abstraction domain-level request va resultni belgilaydi.
Storage-specific pagination, transaction yoki exception contractga chiqib ketmaydi.
Ownership
Vaqtinchalik flag va eski code’ni kim olib tashlashi oldindan belgilanadi.
Migration “deyarli tugagan” holatda yillar qolib ketmasligi uchun cleanup issue va deadline mavjud bo‘ladi.
Release xavfsizligi
Incomplete yangi implementation production package ichida bo‘lishi mumkin, ammo default flag uni ishlatmaydi.
Shunga qaramay yangi code startup, migration yoki dependency loading vaqtida eski behaviorni buzmasligi kerak.
Disabled code ham build va smoke testdan o‘tadi.
Bog‘liq tushunchalar
Trunk-based development, Feature flag, Incremental migration, Abstraction, Dark launch, Dual write, Strangler pattern, Continuous delivery, Refactoring