Legacy — bu sadəcə köhnə kod deyil. Bu, biznesə pul gətirən, lakin inkişafı ləngidən işlək sistemdir. Mobil tətbiqlərin hazırlanmasında legacy Objective-C dilində yazılmış ola, köhnəlmiş kitabxanalardan və ya memarlıq nümunələrindən istifadə edə bilər. CAST Software (2024) hesabatına görə, enterprise layihələrində kod sətirinin orta yaşı 14 ili keçir. Legacy ilə iş strategiyası onun əyləcə çevriləcəyini və ya idarə olunan aktiv olaraq qalacağını müəyyən edir.
Əsas məqamlar
Legacy — istehsalatda işləməyə davam edən, lakin artıq müasir keyfiyyət standartlarına cavab verməyən kod və ya sistem. Legacy köhnəlmiş dildə (məsələn, Swift əvəzinə Objective-C), dəstəklənməyən kitabxanalarda və ya çoxdan anti-nümunə hesab edilən memarlıq nümunələrində yazılmış ola bilər.
Legacy-nin əsas xüsusiyyəti testlərin olmamasıdır. Michael Feathers (2004) tərifinə görə, legacy-kod testləri olmayan koddur. Davranışı təhlükəsiz dəyişdirmək mümkün deyilsə, sistem yaşından asılı olmayaraq legacy statusundadır. Vahid testləri olmayan təzə kod — ilk günün legacy-sidir.
Legacy mütləq pis deyil. Java 8-də yaxşı dizayn edilmiş sistem, korutinləri olan Kotlindəki xaotik koddan daha etibarlı və anlaşıqlı ola bilər. Kodun yaşı keyfiyyət göstəricisi deyil — sistemin dəyişikliklərə və genişlənməyə nə dərəcədə uyğun olması vacibdir.
Hər uğurlu sistem zamanla legacy-yə çevrilir. Bu təbii prosesdir: texnologiyalar kodun yenidən yazıla biləcəyindən daha sürətli inkişaf edir. 5 il əvvəl Swift 2-də yazılmış tətbiq bu gün legacy-dir, baxmayaraq ki, yaradılma anında müasir idi.
Legacy-nin biznes dəyəri çox vaxt qiymətləndirilmir. Sistem sabit işləyir, əməliyyatları emal edir, məlumatları saxlayır — yenidən yazmaq risk daşıyır. Standish Group (2024)-ə görə, tam yenidən yazma layihələrinin 35%-i uğursuzluqla başa çatır. İqtisadi cəhətdən legacy-dən qurtulmaq deyil, onunla işləməyi öyrənmək daha məqsədəuyğundur.
Ən yaxşı strategiyalar — mərhələli miqrasiya, köhnə kodu yeni interfeyslər arxasında inkapsulyasiya etmək və avtomatlaşdırılmış testləşdirmə. Legacy yalnız proqnozlaşdırıla bilən xərclə dəyişikliklərə tab gətirməyi dayandırdıqda problemə çevrilir.
Avtomatik testlərin olmaması — əsas göstərici. Bir kod sətirini dəyişdikdən sonra proqramçı testləri işlədib heç nəyin pozulmadığına əmin ola bilmirsə — qarşınızda legacy var. Əlavə əlamət: yerləşdirmə proseduru saatlar çəkir və əl ilə iş tələb edir.
Sənədləşmə koda uyğun gəlmir — digər marker. Memarlıq diaqramları köhnəlib, şərhlər artıq dəyişmiş davranışı təsvir edir. Time-to-ramp-up yeni proqramçı üçün bir ayı keçir — sistemin yüksək mürəkkəbliyi və aşağı saxlanabilirliyinin əlamətidir.
Əlavə əlamətlər: aydın sərhədləri olmayan monolit memarlıq, əsas yoxlama metodu kimi əl ilə test etmə, uzun CI pipeline (30 dəqiqədən çox), cari versiyaları olmayan kitabxanalardan istifadə və qonşu modulları pozmadan asılılıqları yeniləyə bilməmək.
“Kövrək kod” fenomeni — bir yerdə dəyişiklik üç başqa yeri sındırır. Bu, modulların bir-biri haqqında çox şey bildiyi sıx birləşmənin (tight coupling) nəticəsidir. Coupling nə qədər yüksəkdirsə, sistem bir o qədər tez legacy kateqoriyasına keçir.
Sürətin azalması — əsas risk. Sadə bir funksiyanın əlavə edilməsi kodun öyrənilməsi üçün saatlar və test üçün günlər tələb edir. Stripe (2024)-ə görə, proqramçılar vaxtlarının 33%-ni layihədə legacy modullarının olması ilə birbaşa əlaqəli texniki borcun aradan qaldırılmasına sərf edir.
Ekspertizanın itməsi — orijinal kodun müəllifləri şirkətdən ayrılır, sənədləşmə isə natamamdır. Yeni proqramçılar anlaşılmaz modullara toxunmaqdan qorxur, bu da “donmuş kod” effektinə gətirib çıxarır: modul inkişaf etmir, amma işləməyə davam edir. Belə sistemlərin Bus factor həddindən artıq aşağıdır.
Təhlükəsizlik — köhnəlmiş kitabxanalar məlum zəiflikləri ehtiva edir. OpenSSL 1.0.2 və ya Java layihələrində Jackson-un köhnəlmiş versiyalarından istifadə biznesə reputasiya və müştərilərə başa gələ biləcək təhlükəsizlik insidentlərinə birbaşa yoldur.
Komandanın motivasiyasının azalması ‘— legacy ilə onun yaxşılaşdırılması strategiyası olmadan işləmək proqramçıların məmnuniyyətini azaldır. Komanda məhsulla fəxr etməyi dayandırır, kadr rotasiyası artır, bu da sistemin inkişafını daha da ləngidir.
Xarakteristik testlər — legacy kodunda hər hansı dəyişiklikdən əvvəl ilk addım. Kodu məlum giriş məlumatlarında işlədin və gözlənilən nəticəni qeyd edin. Bu testlər cari davranışı spesifikasiya kimi təsbit edir. Golden master testing — çıxış məlumatlarının istinad faylı ilə müqayisə edildiyi variantdır.
Seam təhlili — davranışı dəyişmədən əlaqələrin qırıla biləcəyi nöqtələrin axtarışı. Michael Feathers bir neçə seam növünü ayırır: preprocessor seam, object seam, link seam. Object seam — ən geniş yayılmış: interfeys vasitəsilə real obyektin test kuklası ilə əvəz edilməsi.
Sprout method və Sprout class — yeni kodu köhnənin içərisinə deyil, yanına əlavə etmə texnikaları. Mövcud metodu dəyişdirmək əvəzinə, lazımi məntiqlə yeni metod yaradın və onu köhnədən çağırın. Bu, işləyən kodu sındırma riskini minimuma endirir.
class LegacyPaymentProcessor {
def process(payment) {
// toxunulmamalı olan 200 sətir legacy kodu
logPayment(payment) // sprout method
}
def logPayment(payment) {
// legacy ilə yanaşı əlavə edilmiş yeni kod
}
}
Strangler Fig nümunəsi — legacy miqrasiyası üçün tövsiyə olunan yanaşma. Yeni modul paralel olaraq yaradılır, trafik tədricən köhnədən yenisinə keçirilir. Köhnə modul sorğu almağı dayandırdıqda təbii şəkildə “ölür”. Nümunə riskləri minimuma endirir və problem olduqda geri qayıtmağa imkan verir.
Branch by Abstraction — köhnə və yeni tətbiq üzərində abstraksiya yaradılan texnika. Müştəri kodu abstraksiyaya keçir, köhnə tətbiq tədricən yenisi ilə əvəz olunur. Nümunə: NetworkService vahid protokolu vasitəsilə AFNetworking-dən Alamofire-ə şəbəkə qatının dəyişdirilməsi.
Mərhələli miqrasiya — keçidin kiçik addımlara bölünməsi: köhnə modulun inkapsulyasiyası → testlərin yazılması → yeni modulun yaradılması → paralel işə salma → köhnə modulun silinməsi. Hər addım sistemin stabil vəziyyəti ilə başa çatır ki, bu da istənilən anda dəyişiklikləri yerləşdirməyə imkan verir.
Tez-tez verilən suallar
Tam yenidən yazmaq — ən riskli variantdır. Big Rewrite layihələrinin yalnız 25%-i vaxtında uğurla başa çatır. Strangler Fig nümunəsini tətbiq etmək daha yaxşıdır: modulları məhsulu dayandırmadan tədricən dəyişdirin. Hər iterasiya biznes dəyəri gətirir və risklər zamana yayılır.
Xarakteristik testlərlə başlayın: modulu məlum məlumatlarda işlədin, nəticəni qeyd edin. Golden master testing — davranışı təsbit etməyin sadə yoludur. Hər dəfə kod sətirinə toxunduqda testlər əlavə edin. 6 aydan sonra reqressiyalardan qoruyan çərçivəniz olacaq.
Sistem sabitdirsə, tez-tez dəyişiklik tələb etmirsə və digər modulların iş sürətinə təsir göstərmirsə — onu olduğu kimi buraxın. “If it ain’t broken, don’t fix it” — aşağı dəyişmə tezliyi olan təcrid olunmuş legacy modulları üçün ağlabatan yanaşmadır. Koda yalnız biznes dəyişiklikləri tələb olunduqda toxunun.
Semantic versioning istifadə edin və addımlarla yeniləyin: patch → minor → major. Hər kitabxana üçün uyğunluq testləri yazın. Dependabot və ya Renovate yeniləmə üçün PR-ların yaradılmasını avtomatlaşdırır. Kitabxana deprecated-dirsə — abstraksiya vasitəsilə əvəzlənməni planlaşdırın.
Texniki borc — təxirə salınmış təkmilləşdirmələrin dəyərini qiymətləndirmək üçün metafora. Legacy — artıq köhnəlmiş konkret sistem və ya kod. Texniki borc bir ayda yığıla bilər, legacy vaxt tələb edir. Hər texniki borc legacy olmur, amma hər legacy texniki borc ehtiva edir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun