Code Smell — kodda potensial problemi göstərən səthi əlamətdir. Termini Kent Beck təqdim etdi və Martin Fowler «Refactoring: Improving the Design of Existing Code” kitabında populyarlaşdırdı. Martin Fowler-a görə, kod iyi mütləq səhv demək deyil, lakin demək olar ki, həmişə təkmilləşdirilə bilənliyi artırmaq üçün refaktorinq ehtiyacını göstərir.
Əsas
Code Smell (kod iyi) — mənbə kodunda dərin problemləri göstərən simptomları ifadə edən metaforadır. Termin özünün rəsmi tərifi yoxdur — bu, proqramçıların təcrübəsinə əsaslanan evristikadır. Martin Fowler və Kent Beck 1999-cu ildı «Refactoring” kitabında ilk dəfə 22 iyi sistemləşdirdilər və onların əksəriyyəti onilliklər sonra da aktuallığını qoruyur.
Code Smell və səhv arasındakı fərqi başa düşmək vacibdir. İy səhv deyil: kod tərtib olunur, işləyir və düzgün nəticə verir. Problem ondadır ki, belə kodu oxumaq, dəyişdirmək və test etmək çətindir. Zamanla hər dəyişikliyin dəyəri artır, refaktorinqin düzgünlüyünə inam isə azalır. Statik analiz alətləri (SonarQube, Detekt, SwiftLint) bir çox iyləri avtomatik aşkarlayır.
Evristik xarakter Code Smell o deməkdir ki, hər uzun metodu bölmək və hər böyük sinifi refaktorinq etmək lazım deyil. Qərarı proqramçı qəbul edir, konteksti qiymətləndirir: dəyişiklik tezliyi, modulun kritikliyi, inkişaf planları. Təcrübəli mühəndislər iyi intuitiv hiss edirlər — kod «xoşagəlməz iy verir”, baxmayaraq ki, formal olaraq bütün qaydalar qorunur.
Fowler 22 iyi bir neçə kateqoriyaya ayırdı. Mobil inkişaf üçün ən aktual olanlar struktur iyləri, obyekt-yönümlü dizayn iyləri və platforma məhdudiyyətləri ilə bağlı spesifik problemlərdir. Hər qrupu real təcrübədən nümunələrlə nəzərdən keçirək.
Long Method (uzun metod) — mobil tətbiqlərdə ən geniş yayılmış iydir. Qeydiyyat forması olan ekran tez-tez 200+ sətir uzunluğunda bir setupUI metodu ehtiva edir ki, bu da bütün View-ləri yaradır, konstrantları qurur, hadisələrə abunə olur və səhvləri idarə edir. Həll yolu: məntiqi bloklara görə metodlara bölmək — configureEmailField, configurePasswordField, setupConstraints, bindViewModel.
Large Class (böyük sinif) — həm göstərməyə, həm naviqasiyaya, həm biznes məntiqinə və həm şəbəkə qarşılıqlı əlaqəsinə cavabdeh olan Activity və ya ViewController. Belə sinif Single Responsibility Principle-i pozur və onlarla sahə və metodu ehtiva edir. Android-də bu çox vaxt müxtəlif ekranların məntiqini ehtiva edən 1000+ sətirli Fragment olur. Həll yolu: presenter/ViewModel ayırmaq, şəbəkə işini repozitoriyaya, naviqasiyanı koordinatora ötürmək.
Duplicate Code (kodun təkrarlanması) — eyni blokların tətbiqin müxtəlif hissələrində kopyalanması. Tipik nümunə: məhsul kartını göstərən iki ekran — kataloqda və seçilmişlərdə. Əgər göstərmə məntiqi kopyalanıbsa, bir yerdə səhvin düzəldilməsi digər yerdə onu düzəltməyəcək. Həll yolu: ümumi məntiqi təkrar istifadə olunan komponentə və ya genişləndirməyə çıxarmaq.
Feature Envy (başqa sinifə həsəd) — bir sinfin metodu digər sinfin məlumatlarından intensiv istifadə edir. Android-də bu, ViewModel-in User modelinin metodunu çağırmaq əvəzinə birbaşa onun sahələrinə müraciət etməsində özünü göstərir. Siqnal: əgər metodu məlumatlarından istifadə etdiyi sinfə köçürmək olarsa — köçürün. Switch Statements (şərt zəncirləri) — obyektin növünü yoxlayan switch və ya if-else zənciri. Bunun əvəzinə polimorfizm və ya strategy pattern istifadə edilməlidir.
Data Class — yalnız məlumat saxlayan, lakin davranışı olmayan sinif. Data class (Kotlin-də) və ya struktur (Swift-də) özlüyündə iy deyil. Problem o zaman yaranır ki, bu məlumatlarla işləyən biznes məntiqi inkapsulyasiya olunmaq əvəzinə bütün kod bazasına yayılır. Refused Bequest — varis valideynin metodlarının əksəriyyətindən istifadə etmir və onları boş şablonlarla ləğv edir. Yanlış vəris əlaməti: vərisi kompozisiya ilə əvəz edin.
God Activity / God Fragment — hər şeyi bilən Activity və ya Fragment: həyat dövü, məlumatlar, naviqasiya, icazələr, DI haqqında. Bu, tətbiqin saxlanması ən bahalı sinfidir. Həll yolu: MVVM, MVI və ya Clean Architecture memarlıq nümunələri məsuliyyəti bölür. Giant ViewController — iOS üçün analoq, burada UIViewController ekranın bütün məntiqini ehtiva edir və çox vaxt 500 sətirdən çox olur.
Hardcoded Resources — sətrlər, rənglər, ölçülər, API URL-ləri birbaşa kodun içinə yerləşdirilib. Android-də bu R resurs sistemindən istifadəni pozur, iOS-də isə NSLocalizedString və Asset Catalog-ı. Düzəliş: bütün sətrləri strings.xml və ya Localizable.strings fayllarına, URL-ləri konfiqurasiya faylına, ölçüləri dimens-ə çıxarın. Leaking Context — Activity və ya ViewController referansını komponentin özündən daha uzun saxlamaq. Yaddaş sızıntısına və qəzaya səbəb olur. Həll yolu: zəif referanslar, Jetpack Lifecycle, RxSwift DisposeBag.
| İy | Harada rast gəlinir | Həll yolu |
|---|---|---|
| Long Method | Android/iOS | Extract Method, bölmə |
| Large Class | Activity, ViewController | MVVM, VIPER, Clean Arch |
| Duplicate Code | İstənilən ekran | Shared Component, DRY |
| Feature Envy | ViewModel, Presenter | Move Method |
| Leaking Context | Android | Həyat dövündən xəbərdar komponentlər |
Code review — iyləri aşkarlamağın ən etibarlı üsulu. İnsan gözü avtomatik analizatorların qaçırdığı qeyri-təbii konstruksiyaları görür. Kod nəzərdən keçirmənin səmərəliliyi artır, əgər komanda tipik iylərin yoxlama siyahısından istifadə edərsə. Bir seansda 200–400 sətirdən çox kod yoxlanılması tövsiyə edilmir — bu həddən sonra diqqət azalır və iylər gözdən qaçır.
Statik analiz struktur iylərinin axtarışını avtomatlaşdırır. Android üçün standart alətlər Detekt (Kotlin) və Android Lint, iOS üçün isə SwiftLint və SonarQube-dir. Bu alətlər uzun metodları, böyük sinifləri, kod təkrarlanmasını və bir çox digər problemləri tapır. Qaydaları layihəyə uyğun konfiqurasiya etmək vacibdir — standart konfiqurasiyalar çox vaxt çox sərt və ya əksinə, kritik iyləri qaçırır.
Kod metrikaları obyektiv meyarlar verir: Cyclomatic Complexity (hədd >10 diqqət tələb edir), Lines of Code per Method (hədd >30), Depth of Inheritance (>3 — düşünmək üçün səbəb). CodeMetrics (Xcode) və Gradle Metrics Plugin kimi alətlər zamanla metrikaların dəyişiklik qrafiklərini qurur. ƏGər metodun mürəkkəbliyi son kommittdən sonra 5-dən 15-ə yüksəlibsə — bu refaktorinq üçün siqnaldır.
// Nümunə: Cyclomatic mürəkkəbliyi = 7 olan metod (hədd 5-dən yuxarı)
fun processOrder(order: Order) {
if (order.status == Status.NEW) { /* 10 sətir */ }
else if (order.status == Status.PAID) { /* 15 sətir */ }
else if (order.status == Status.SHIPPED) { /* 20 sətir */ }
else if (order.status == Status.DELIVERED) { /* 8 sətir */ }
else if (order.status == Status.CANCELLED) { /* 5 sətir */ }
else { throw IllegalStateException() }
}
// Düzəliş: switch əvəzinə polimorfizm
interface OrderHandler {
fun handle(order: Order)
}
Avtomatik iy axtarışı kod nəzərdən keçirməni əvəz etmir: statik analizatorlar yalnız struktur problemləri tapır, lakin semantik iyləri (Feature Envy, Inappropriate Intimacy) aşkarlaya bilmir. Avtomatik alətlər və insan nəzarətinin birləşməsi ən yaxşı nəticəni verir. CI/CD boru kəmərini elə konfiqurasiya edin ki, mürəkkəblik və ya metod uzunluğu hədləri aşıldıqda qurma uğursuz olsun.
Refaktorinq — kod iylərini aradan qaldırmağın əsas üsuludur. Fowler onlarla refaktorinq texnikasını təsvir edir, hər biri müəyyən iyə tətbiq olunur. Extract Method — uzun metodlar üçün, Extract Class — böyük siniflər üçün, Move Method — Feature Envy üçün. Refaktorinqi kiçik addımlarla yerinə yetirmək, hər dəyişiklikdən sonra kodun işləkliyini qorumaq vacibdir.
Refaktorinqdən əvvəl testlər — məcburi şərtdir. ƏGər kod vahid testlərlə əhatə olunmayıbsa, refaktorinq naməlum nəticə ilə yenidən yazmağa çevrilir. Testləri olmayan legacy kod üçün Characterisation Tests istifadə edin — cari davranışı qeyd edən testlər yazın, sonra refaktorinq edin. Test etmə refaktorinqdən sonra biznes məntiqinin pozulmadığına əminlik verir.
Tədricilik — mobil inkişafda iylərin uğurlu aradan qaldırılmasının açarıdır. God Activity-ni tamamilə yenidən yazmağa çalışmayın. Əvvəlcə naviqasiya qatını, sonra məlumat qatını, daha sonra göstərmə məntiqini ayırın. Hər addımı kommit və testlərlə müşayiət edin. Feature toggle istifadə edərək refaktorinqi istifadəçilərin bir hissəsi üçün aktivləşdirin və problem olduqda geri qaytarın.
IDE alətləri bir çox refaktorinq texnikasını avtomatlaşdırır. Android Studio və IntelliJ IDEA daxili refaktorinqlər təklif edir: Extract Method, Extract Interface, Pull Members Up, Encapsulate Fields. Xcode (versiya 14-dən başlayaraq) Swift üçün refaktorinq dəstəyini yaxşılaşdırdı. Avtomatik refaktorinqlərdən istifadə kodun əllə kopyalanması ilə müqayisədə səhv riskini azaldır.
Mobil inkişaf platforma məhdudiyyətləri ilə bağlı öz spesifik iylərini əlavə edir. Android-də bu, Context sızıntısı, bağlanmamış Cursor, Lifecycle-in düzgün istifadə edilməməsidir. iOS-də — closure-lar vasitəsilə retain cycle, Auto Layout ilə yanlış iş, nəhəng ViewController. Bu iylər təkcə saxlanmanı pisləşdirmir, həm də birbaşa performansa və tətbiqin sabitliyinə təsir edir.
Callback Hell — asinxron əməliyyatlarla işləyən kod üçün xarakterik iydir. İç-içə callback-lər (callback inside callback) kodu oxunmaz və çətin sazlanan edir. Həll yolu: korutinlər (Kotlin), async/await (Swift 5.5+), RxJava/RxSwift və ya Combine. Google I/O 2023 məlumatlarına görə, callback üslubundan korutinlərə keçən layihələr səhvlərin sayını 30% azaldır və yeni funksiyaların əlavə edilməsini sürətləndirir.
Platform Coupling — biznes məntiqinin platforma komponentlərinə sərt bağlılığı. Belə məntiqin test edilməsi emulyatorun işə salınmasını tələb edir, bu da əks əlaqə dövrünü yavaşladır. Düzəliş: Clean Architecture kodu Domain (platformadan asılı olmayan təmiz Kotlin/Swift) və Data/UI (platforma asılılıqları ilə) qatlarına ayırır. Biznes məntiqi emulyatorsuz JVM-də test edilir.
Tez-tez verilən suallar
Xeyr — Code Smell səhv deyil. İyli kod düzgün işləyir, lakin onu saxlamaq, dəyişdirmək və test etmək çətindir. Səhv — yanlış davranış, iy isə gələcəkdə potensial problemlər barədə xəbərdarlıqdır.
22 iy «Refactoring” kitabının ikinci nəşrində (2019). Bunlara Long Method, Large Class, Primitive Obsession, Data Clumps, Switch Statements, Speculative Generality və digərləri daxildir. İcma müasir paradiqmalar və platformalar üçün onlarla yeni iy əlavə etdi.
Birləşmə ən yaxşı nəticəni verir: avtomatik analiz üçün Detekt (Android/Kotlin), SwiftLint (iOS), SonarQube (hər ikisi) və semantik iylər üçün kod nəzərdən keçirmə. Heç bir alət 100% problem tapmır — insan təcrübəsi həlledici olaraq qalır.
Bəli, əgər kod nadir hallarda dəyişirsə və ya yaxın gələcəkdə tamamilə yenidən yazılacaqsa. Lakin iylərin yığılması texniki borca çevrilir: hər yeni dəyişiklik getdikcə çətinləşir və düzəltmə dəyəri eksponensial olaraq artır.
Bəli — deklarativ çərçivələr yeni iylər yaratdı: nəhəng @State blokları, təkrari renderlərlə yanlış iş, həddindən artıq recomposition, ayrıca View-lərə çıxarmanın olmaması. SwiftUI üçün tipik iy onlarla @State dəyişəni olan Massive View-dir.
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