Modulyarlıq — tətbiqin hər biri bir funksionallığa cavabdeh olan müstəqil modullardan yığıldığı prinsipdir. Android Developers-ə görə, modullara bölmə paralel kompilyasiya hesabına qurulmanı sürətləndirir və komandalara tətbiqin müxtəlif hissələri üzərində müstəqil işləməyə imkan verir. Modul arxitekturası onlarla tərtibatçısı olan böyük mobil layihələr üçün standart halına gəlib.
Əsas məqamlar
Modulyarlıq — kodu təşkil etmə üsuludur ki, tətbiq zəif bağlı modullardan ibarət olur, hər biri ictimai interfeys vasitəsilə ciddi müyyən edilmiş funksionallıq təmin edir. Bütün siniflərin bir layihədə olduğu monolit arxitekturadan fərqli olaraq, modul yanaşması kodu fiziki cəhətdən müstəqil qurulma vahidlərinə bölür.
Modulyarlığın əsas məqsədi mürəkkəbliyi idarə etməkdir. Tərtibatçı bütün kod bazasını beynində saxlamadan bir modula fokuslana bilər. Hər modulun öz məsuliyyət zonası var və qalanlarından asılı olmayaraq inkişaf etdirilə, test edilə və yerləşdirilə bilər. Bu, xüsusilə 10+ tərtibatçısı olan layihələrdə dəyərlidir, çünki monolit üzərində paralel iş tez-tez birləşmə konfliktlərinə gətirib çıxarır.
Modulyarlığı qat arxitekturasından fərqləndirmək vacibdir. Qatlar (Presentation, Domain, Data) kodu texniki meyarla, modullar isə funksional meyarla bölür. “İstifadəçi profili” modulu öz daxilində öz qatlarını ehtiva edə bilər. Praktikada modul yanaşması və qat arxitekturası birləşdirilir: hər modulun öz üçqatlı strukturu var.
Feature-modullar — ən populyar modul növü. Hər ekran və ya əlaqəli ekranlar qrupu ayrıca modula ayrılır: Onboarding, Profile, Settings, Feed. Feature-modul funksiyanın işləməsi üçün lazım olan hər şeyi ehtiva edir: UI, biznes məntiqi, data qatı. Modulun sərhədləri qorunur — digər funksiyalar onun daxili siniflərinə daxil ola bilməz.
Core-modullar ümumi infrastrukturu ehtiva edir: şəbəkə ilə iş, verilənlər bazası, analitika, dizayn sistemi. Onlar feature-modullardan asılı deyil, lakin feature-modullar onlardan asılıdır. Bu bölgü analitik SDK-nın dəyişdirilməsinin şəbəkə qatına təsir etməyəcəyinə zəmanət verir və əksinə. Core-modullar kod təkrarlanmadan funksiyalar arasında təkrar istifadə olunur.
Shared-modullar bir neçə funksiya tərəfindən istifadə olunan kodu ehtiva edir: verilənlər modelləri, utilitalar, sabitlər, fərdi View-lər. Shared-modulların əsas problemi zamanla müxtəlif kodun yığıldığı zibilxanaya (“misc module”) çevrilmə riskidir. Qayda: shared-modulun dəqiq mövzusu olmalıdır, məsələn “shared-ui” və ya “shared-models”.
Android-də shared-modullar tez-tez lib prefiksi ilə kitabxanalara ayrılır: lib-network, lib-database, lib-ui-components. iOS-da eyni funksiyaları Workspace daxilində daxili Swift Packages yerinə yetirir. Praktikada komandalar 3–5 shared-modulla məhdudlaşır ki, qurulmanı çətinləşdirən həddindən artıq asılılıq şəbəkəsi yaranmasın.
Ayrıca test modulları yalnız dəyişdirilmiş modul üçün testləri işə salmağa imkan verir, bütün test bazasını işə salmadan. Bu, CI/CD pipeline müddətini saatlardan dəqiqələrə endirir. Modullar qurulma səviyyəsində ayrılmanı təmin edir: şəbəkə qatının modulu testlərdə təsadüfən UI kitabxanalarını import edə bilməz.
Hər modulun dəqiq müyyən edilmiş ictimai API-si olmalıdır. Android-də buna giriş modifierləri və Gradle-də api vs implementation vasitəsilə nail olunur. iOS-da — public/internal giriş modifierləri və Package.swift vasitəsilə idarə olunan asılılıqlar. Görünürlüyü minimum zəruri səviyyəyə endirmək modul dizaynının əsas təcrübəsidir.
Gradle modul arxitekturasını yerli olaraq dəstəkləyir: hər modul öz build.gradle faylı olan ayrıca qurulma vahididir. Android layihələri application modulu (app) və bir neçə library modulunun kombinasiyasından istifadə edir. Kitabxana modulları tətbiq kimi işə salına bilməz, lakin AAR kimi repozitoriyada dərc edilə bilər.
Gradle-in əsas xüsusiyyəti müstəqil modulların paralel qurulmasıdır. A, B və C modulları bir-birindən asılı deyilsə, Gradle onları eyni vaxtda, prosessorun bütün nüvələrindən istifadə edərək kompilyasiya edir. 20+ modulu olan layihələrdə bu, tam qurulmanı 15 dəqiqədən 3–5 dəqiqəyə endirir. Dəyişdirilmiş modulun inkremental qurulması saniyələr çəkir.
Gradle modullar arasında iki növ asılılıq təmin edir: api (tranzitiv) və implementation (qeyri-tranzitiv). Fərq modulyarlıq üçün kritik əhəmiyyət daşıyır: implementation modulun istehlakçılarından tranzitiv asılılıqları gizlədir. :profile modulu :networking-i implementation vasitəsilə istifadə edirsə, :profile istehlakçıları :networking haqqında bilmir və ona müraciət edə bilməz.
// settings.gradle — modulların deklarasiyası
include ':app'
include ':feature:profile'
include ':feature:settings'
include ':core:network'
include ':core:database'
// build.gradle feature/profile — modul asılılıqları
dependencies {
implementation project(':core:network')
implementation project(':core:database')
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0'
}
Kod modul Android layihəsinin strukturunu göstərir. Settings.gradle bütün modulları sadalayır, hər feature-modulun build.gradle-ı isə yalnız ehtiyac duyduğu core-modulları göstərir. Qurulma sistemi avtomatik olaraq tranzitiv asılılıqları həll edir və modulları düzgün ardıcıllıqla yığır.
Swift Package Manager (SPM) — 2019-cu ildən iOS-da modulyarlıq üçün standart alət. SPM tətbiqi hər biri kitabxana və ya icra edilə bilən fayl ola bilən Swift Packages-ə bölməyə imkan verir. Package modulları (targets) və onların asılılıqlarını Package.swift vasitəsilə müyyən edir. SPM Xcode ilə inteqrasiya olunub və əlavə alətlər tələb etmir.
CocoaPods xarici kitabxanalar üçün əsas asılılıq meneceri olaraq qalır. Podfile və Podspec modul strukturunu təyin edir, CocoaPods isə ayrıca pod layihələri ilə workspace yaradır. Layihənin öz modulyarlığı üçün komandalar getdikcə daha çox SPM-i seçirlər, çünki Xcode-a daxildir və quraşdırma tələb etmir.
iOS modulyarlığında giriş nəzarəti mühüm rol oynayır: public, package, internal, fileprivate və private. Modul yalnız digər modullar üçün əlçatan olmalı olan tipləri dərc edir. Tətbiqin daxili detalları internal və private modifierləri arxasında gizlənir. Bu, modullar arasında gizli asılılıqların yaranmasının qarşısını alır.
// Package.swift — iOS layihəsinin modul strukturu
let package = Package(
name: "MyApp",
platforms: [.iOS(SupportedPlatform.iOSVersion.v17)],
products: [
.library(name: "ProfileFeature", targets: ["ProfileFeature"]),
.library(name: "NetworkCore", targets: ["NetworkCore"]),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0")
],
targets: [
.target(name: "ProfileFeature", dependencies: ["NetworkCore"]),
.target(name: "NetworkCore", dependencies: ["Alamofire"]),
]
)
Package.swift iki kitabxana məhsulunu bəyan edir: ProfileFeature və NetworkCore. ProfileFeature NetworkCore-dan asılıdır, lakin Alamofire-in mövcudluğundan xəbərsizdir — o NetworkCore daxilində gizlənib. Belə izolyasiya modul səviyyəsində ayrılmanın birbaşa tətbiqidir: HTTP müştərisindəki dəyişikliklər ProfileFeature-in yenidən kompilyasiyasını tələb etmir.
Modulyarlığın əsas üstünlüyü inkişaf sürətidir. Komandalar müxtəlif modullar üzərində koddakı konfliktlər olmadan paralel işləyir. CI/CD pipeline yalnız dəyişdirilmiş modulları yığır və yalnız onların testlərini işə salır. Geribildirim müddəti qısalır, buraxılış tezliyi artır. Spotify, Uber və Airbnb modul arxitekturasına miqrasiya hallarını 2–3 dəfə metrik yaxşılaşması ilə dərc ediblər.
İkinci üstünlük — səhvlərin izolyasiyası. Profile modulundakı xəta Payments moduluna təsir etmir, əgər aralarında birbaşa asılılıqlar yoxdursa. Bu, yüksək riskli funksiyaları (ödənişlər, tibbi məlumatlar) olan tətbiqlərdə xüsusilə vacibdir ki, əlaqəsiz ekrandakı xəta kritik funksionallığın buraxılışını bloklamasın.
Əsas çətinlik — asılılıqların idarə edilməsi. Səhv dizaynda bir modulun dəyişdirilməsi onlarla digər modulun kaskadlı şəkildə yenidən yığılmasına səbəb olan modul qrafı yaranır. Həll — asikliklik qaydasına riayət etmək: modul asılılıqları qrafı istiqamətlənmiş asiklik qraf (DAG) olmalıdır. Gradle Module Graph Assert kimi alətlər qurulma mərhələsində dövrləri aşkarlamağa kömək edir.
İkinci çətinlik — ilkin konfiqurasiya müddətinin artması. Modul arxitekturasının yaradılması layihənin ilkin mərhələsində daha çox vaxt tələb edir. 1–3 tərtibatçısı olan kiçik layihələr modulyarlıqdan faydalanmaya bilər, paralelləşdirməyə real ehtiyac olmadan modul sərhədlərini saxlamağa vaxt sərf edər. Həll — monolitdən başlamaq və komanda böyüdükcə modulları ayırmaqdır.
Feature-first yanaşması modulları funksionallığa görə qruplaşdırır: hər ekran və ya ekranlar qrupu ayrıca modul olur. Layer-first yanaşması kodu texniki meyarla bölür: UI, biznes məntiqi və məlumatlar üçün ayrıca modullar. Praktikada əksər komandalar core-modulları olan feature-first seçir — bu, daha yaxşı izolyasiya və layihədə aydın naviqasiya verir.
Yanaşmalar arasında seçim komandanın ölçüsündən və funksionallığın proqnozlaşdırıla bilməsindən asılıdır. Layihədə hansı ekranların olacağını dəqiq bilirsinizsə, feature-first hər tərtibatçıya öz modulu üçün cavabdeh olmağa imkan verir. Funksionallıq tez-tez dəyişir və ekranlar arasında kəsişirsə, layer-first müxtəlif funksiyalar arasında kodun təkrar istifadəsində daha çox elastiklik verir.
Tez-tez verilən suallar
Optimal say layihənin və komandanın ölçüsündən asılıdır. 5 nəfərlik komanda üçün 6–10 modul kifayətdir. 20+ tərtibatçı üçün — 20–40 modul. Qayda: modul bir tərtibatçının tamamilə anlaması üçün kifayət qədər kiçik və həddindən artıq asılılıq şəbəkəsi yaratmamaq üçün kifayət qədər böyük olmalıdır.
Düzgün modulyarlıq paralel kompilyasiya və keşləmə hesabına qurulmanı sürətləndirir. Lakin sıx asılılıqları olan həddindən artıq modul qurulmanı yavaşladır — Gradle və Xcode qrafın həllinə vaxt sərf edir. Sürətli qurulmanın açarı — tranzitiv asılılıqların minimallaşdırılması və asiklikliyə riayət etməkdir.
Bəli, lakin iterativ şəkildə. Core-modulları (şəbəkə, verilənlər bazası) ayırmaqla başlayın, sonra funksiyaları bir-bir çıxarın. Köhnə monolit kodla paralel olaraq yeni modul kodu işə salmaq üçün feature flags istifadə edin. Böyük tətbiqin tam miqrasiyası 3 aydan 12 aya qədər çəkir.
Modullar bir tətbiq daxilində kompilyasiya vahidləridir. Mikroservislər — müxtəlif serverlərdə işləyən ayrıca proseslərdir. Modullar kodu bölür, mikroservislər iş vaxtını bölür. Mobil inkişafda tez-tez “microapps” termini hibrid kimi istifadə olunur: müstəqil tətbiqlər kimi işə salına bilən feature-modullar.
Hər modulun müstəqil işə salınan öz vahid testləri var. İnteqrasiya testləri modullar arasında qarşılıqlı əlaqəni yoxlayır. UI testləri mock-məlumatlarla feature-modulları əhatə edir. Modul arxitekturası testləri asanlaşdırır: başqa modulun asılılığını mock etmək monolitin bir hissəsini mock etməkdən daha asandır.
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